From 470981d3b4958cbc13c6e7077e23a4d8faf47943 Mon Sep 17 00:00:00 2001 From: seven Date: Sun, 31 Mar 2024 17:46:20 +0800 Subject: [PATCH] feat: implement shortcuts of open documentation for current request #36 (#39) https://github.com/geek-fun/dockit/issues/36 Signed-off-by: seven --- docs/dockit-actions.md | 37 ++++++++++ docs/index.md | 3 + src/common/editor.ts | 135 ++++++++++++++++++++++++++++++++++++- src/electron/main.ts | 3 + src/electron/preload.ts | 2 + src/views/editor/index.vue | 26 +++++-- src/vite-env.d.ts | 1 + 7 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 docs/dockit-actions.md create mode 100644 docs/index.md diff --git a/docs/dockit-actions.md b/docs/dockit-actions.md new file mode 100644 index 00000000..b65268f9 --- /dev/null +++ b/docs/dockit-actions.md @@ -0,0 +1,37 @@ +# DocKit Actions +## Overview +DocKit Actions are the all actions that DocKit can execute, there are the tables outlined the actions currently available in DocKit. + +| Command | DocLinks | Curl Command Sample | Description | Status | +|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|--------| +| POST_INDEX | [indices-create-index.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-create-index.html) | ```bash curl -X POST "http://localhost:9200/my_index/_doc/1" -H 'Content-Type: application/json' -d '{"name": "Elasticsearch", "category": "Search Engine"}' ``` | Adds or updates a JSON document in an index. | | +| POST_SEARCH | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-search.html | ```bash curl -X GET "http://localhost:9200/my_index/_search" -H 'Content-Type: application/json' -d '{"query": {"match": {"name": "Elasticsearch"}}}' ``` | Performs a search query on one or more indices. | | +| POST_COUNT | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-count.html | ```bash curl -X GET "http://localhost:9200/my_index/_count" -H 'Content-Type: application/json' -d '{"query": {"term": {"category.keyword": "Search Engine"}}}' ``` | Returns the number of documents that match a query. | | +| GET_SEARCH | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/docs-get.html | ```bash curl -X GET "http://localhost:9200/my_index/_doc/1"``` | Retrieves a document by its index, type, and ID. | | +| POST_UPDATE | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/docs-update.html | ```bash curl -X POST "http://localhost:9200/my_index/_update/1" -H 'Content-Type: application/json' -d '{"doc": {"category": "Search Engine"}}' ``` | Updates a document without fetching it first. | | +| DELETE_DOC | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/docs-delete.html | ```bash curl -X DELETE "http://localhost:9200/my_index/_doc/1"``` | Deletes a document by its index, type, and ID. | | +| PUT_INDEX | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-create-index.html | ```bash curl -X PUT "http://localhost:9200/my_index"``` | Creates an index. | | +| DELETE_INDEX | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-delete-index.html | ```bash curl -X DELETE "http://localhost:9200/my_index"``` | Deletes an index. | | +| POST_BULK | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/docs-bulk.html | ```bash curl -X POST "http://localhost:9200/_bulk" -H 'Content-Type: application/json' -d '{"index": {"_index": "my_index", "_id": "1"}}\n{"name": "Document 1"}\n{"delete": {"_index": "my_index", "_id": "2"}}'``` | Performs multiple index, create, update, or delete operations in a single request. | | +| PUT_PUT_INDEX | [indices-create-index.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-create-index.html) | | | | +| PUT_MAPPING | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-put-mapping.html | ```bash curl -X PUT "http://localhost:9200/my_index/_mapping" -H 'Content-Type: application/json' -d '{"properties": {"name": {"type": "text"}}}'``` | Defines a mapping for a type. | | +| GET_MAPPING | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-get-mapping.html | ```bash curl -X GET "http://localhost:9200/my_index/_mapping"``` | Retrieves the mapping definition of an index. | | +| POST_ALIAS | [indices-aliases.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-aliases.html) | ```bash curl -X POST "http://localhost:9200/_aliases" -H 'Content-Type: application/json' -d '{"actions": [{"add": {"index": "my_index", "alias": "alias_name"}}]}'``` | Manages index aliases. | | +| GET_HEALTH | https://www.elastic.co/guide/en/elasticsearch/reference/8.2/cluster-health.html | ```bash curl -X GET "http://localhost:9200/_cluster/health"``` | Provides information about the cluster health. | | +| GET_STATE | [indices-stats.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-stats.html) | ```bash curl -X GET "http://localhost:9200/_cluster/state"``` | Returns the cluster state. | | +| GET_INFO | | ```bash curl -X GET "http://localhost:9200/_nodes/info"``` | Provides information about nodes in the cluster. | | +| HEAD_INDEX | [indices-exists.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-exists.html) | ```bash curl -I -X HEAD "http://localhost:9200/{index}"``` | Checks if an index exists. | | +| PUT_AUTO_FOLLOW | [ccr-put-auto-follow-pattern.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/ccr-put-auto-follow-pattern.html) | ```bash curl -X PUT "http://localhost:9200/_ccr/auto_follow/my_auto_follow" -H 'Content-Type: application/json' -d '{"remote_cluster": "remote_cluster_name", "leader_index_patterns": ["leader_index_pattern"], "follow_index_pattern": "follow_index_pattern"}'``` | Creates an auto-follow pattern. | | +| PUT_CCR_FOLLOW | [ccr-put-follow.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/ccr-put-follow.html) | ```bash curl -X PUT "http://localhost:9200/{index}/_ccr/follow" -H 'Content-Type: application/json' -d '{"remote_cluster": "remote_cluster_name", "leader_index": "leader_index_name"}'``` | Creates a follower index. | | +| PUT_SLM_POLICY | [slm-api-put-policy.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/slm-api-put-policy.html) | ```bash curl -X PUT "http://localhost:9200/_slm/policy/{policy_id}" -H 'Content-Type: application/json' -d '{"policy": {"some_settings": "some_values"}}'``` | Configures a snapshot lifecycle management policy. | | +| PUT_SECURITY_ROLE_MAPPING | [security-api-put-role-mapping.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/security-api-put-role-mapping.html) | ```bash curl -X PUT "http://localhost:9200/_security/role_mapping/{name}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Defines a role mapping. | | +| PUT_ROLLUP_JOB | [rollup-put-job.html#rollup-put-job-api-request-body](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/rollup-put-job.html#rollup-put-job-api-request-body) | ```bash curl -X PUT "http://localhost:9200/_rollup/job/{id}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates or updates a rollup job. | | +| PUT_SECURITY_API_KEY | [security-api-create-api-key.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/security-api-create-api-key.html) | ```bash curl -X POST "http://localhost:9200/_security/api_key" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates an API key. | | +| PUT_INGEST_PIPELINE | [put-pipeline-api.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/put-pipeline-api.html) | ```bash curl -X PUT "http://localhost:9200/_ingest/pipeline/{id}" -H 'Content-Type: application/json' -d '{"pipeline": {"description": "description", "processors": [{"some_processor": "some_settings"}]}}'``` | Creates or updates an ingest pipeline. | | +| PUT_TRANSFORM | [put-transform.html#put-transform-request-body](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/put-transform.html#put-transform-request-body) | ```bash curl -X PUT "http://localhost:9200/_transform/{transform_id}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates or updates a transform. | | +| POST_ML_INFER | [infer-trained-model.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/infer-trained-model.html) | ```bash curl -X POST "http://localhost:9200/_ml/infer/{model_id}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Infers results using a trained model. | | +| POST_MULTI_SEARCH | [search-multi-search.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/search-multi-search.html) | ```bash curl -X POST "http://localhost:9200/{index}/_msearch" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Executes multiple search requests within a single API call. | | +| POST_OPEN_INDEX | [indices-open-close.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-open-close.html) | ```bash curl -X POST "http://localhost:9200/{index}/_open"``` | Opens an index. | | +| PUT_COMPONENT_TEMPLATE | [indices-component-template.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-component-template.html) | ```bash curl -X PUT "http://localhost:9200/_component_template/{name}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates or updates a component template. | | +| PUT_ENRICH_POLICY | [put-enrich-policy-api.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/put-enrich-policy-api.html) | ```bash curl -X PUT "http://localhost:9200/_enrich/policy/{name}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates or updates an enrich policy. | | +| PUT_TEMPLATE | [indices-templates-v1.html](https://www.elastic.co/guide/en/elasticsearch/reference/8.2/indices-templates-v1.html) | ```bash curl -X PUT "http://localhost:9200/_template/{name}" -H 'Content-Type: application/json' -d '{"some_settings": "some_values"}'``` | Creates or updates an index template. | | diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..092e8faf --- /dev/null +++ b/docs/index.md @@ -0,0 +1,3 @@ +# Index page +this docs folder contains the documentation for the project. + diff --git a/src/common/editor.ts b/src/common/editor.ts index 0a6206d5..043e2f07 100644 --- a/src/common/editor.ts +++ b/src/common/editor.ts @@ -15,7 +15,7 @@ export const executeActions = { decorationClassName: 'action-execute-decoration', }; -export type SearchToken = { +export type SearchAction = { qdsl: string; actionPosition: Range; qdslPosition: Range; @@ -247,7 +247,7 @@ export const buildSearchToken = (lines: Array<{ lineNumber: number; lineContent: endColumn: lines[endLineNumber].lineContent.length, } : null, - } as SearchToken; + } as SearchAction; }); }; @@ -343,3 +343,134 @@ POST _bulk {"name": "Document 1"} {"delete": {"_index": "dockit_sample_index", "_id": "2"}} `; +export enum ActionType { + POST_INDEX = 'POST_INDEX', + POST_SEARCH = 'POST_SEARCH', + POST_COUNT = 'POST_COUNT', + GET_SEARCH = 'GET_SEARCH', + POST_UPDATE = 'POST_UPDATE', + DELETE_DOC = 'DELETE_DOC', + PUT_INDEX = 'PUT_INDEX', + DELETE_INDEX = 'DELETE_INDEX', + POST_BULK = 'POST_BULK', + PUT_PUT_INDEX = 'PUT_PUT_INDEX', + PUT_MAPPING = 'PUT_MAPPING', + GET_MAPPING = 'GET_MAPPING', + POST_ALIAS = 'POST_ALIAS', + GET_HEALTH = 'GET_HEALTH', + GET_STATE = 'GET_STATE', + GET_INFO = 'GET_INFO', + HEAD_INDEX = 'HEAD_INDEX', + PUT_AUTO_FOLLOW = 'PUT_AUTO_FOLLOW', + PUT_CCR_FOLLOW = 'PUT_CCR_FOLLOW', + PUT_SLM_POLICY = 'PUT_SLM_POLICY', + PUT_SECURITY_ROLE_MAPPING = 'PUT_SECURITY_ROLE_MAPPING', + PUT_ROLLUP_JOB = 'PUT_ROLLUP_JOB', + PUT_SECURITY_API_KEY = 'PUT_SECURITY_API_KEY', + PUT_INGEST_PIPELINE = 'PUT_INGEST_PIPELINE', + PUT_TRANSFORM = 'PUT_TRANSFORM', + POST_ML_INFER = 'POST_ML_INFER', + POST_MULTI_SEARCH = 'POST_MULTI_SEARCH', + POST_OPEN_INDEX = 'POST_OPEN_INDEX', + PUT_COMPONENT_TEMPLATE = 'PUT_COMPONENT_TEMPLATE', + PUT_ENRICH_POLICY = 'PUT_ENRICH_POLICY', + PUT_TEMPLATE = 'PUT_TEMPLATE', +} + +const actionRegexMap: { [key in ActionType]: RegExp } = { + POST_INDEX: /POST \/_doc\/\d+/, + POST_SEARCH: /POST \/_search/, + POST_COUNT: /POST \/_count/, + GET_SEARCH: /GET \/_doc\/\d+/, + POST_UPDATE: /POST \/_update\/\d+/, + DELETE_DOC: /DELETE \/_doc\/\d+/, + PUT_INDEX: /PUT /, + DELETE_INDEX: /DELETE /, + POST_BULK: /POST \/_bulk/, + PUT_PUT_INDEX: /PUT /, + PUT_MAPPING: /PUT \/_mapping/, + GET_MAPPING: /GET \/_mapping/, + POST_ALIAS: /POST \/_aliases/, + GET_HEALTH: /GET \/_cluster\/health/, + GET_STATE: /GET \/_cluster\/state/, + GET_INFO: /GET \/_nodes\/info/, + HEAD_INDEX: /HEAD /, + PUT_AUTO_FOLLOW: /PUT \/_ccr\/auto_follow\/\w+/, + PUT_CCR_FOLLOW: /PUT \/_ccr\/follow/, + PUT_SLM_POLICY: /PUT \/_slm\/policy\/\w+/, + PUT_SECURITY_ROLE_MAPPING: /PUT \/_security\/role_mapping\/\w+/, + PUT_ROLLUP_JOB: /PUT \/_rollup\/job\/\w+/, + PUT_SECURITY_API_KEY: /PUT \/_security\/api_key/, + PUT_INGEST_PIPELINE: /PUT \/_ingest\/pipeline\/\w+/, + PUT_TRANSFORM: /PUT \/_transform\/\w+/, + POST_ML_INFER: /POST \/_ml\/infer\/\w+/, + POST_MULTI_SEARCH: /POST \/_msearch/, + POST_OPEN_INDEX: /POST \/_open/, + PUT_COMPONENT_TEMPLATE: /PUT \/_component_template\/\w+/, + PUT_ENRICH_POLICY: /PUT \/_enrich\/policy\/\w+/, + PUT_TEMPLATE: /PUT \/_template\/\w+/, +}; +export enum EngineType { + ELASTICSEARCH = 'ELASTICSEARCH', + OPENSEARCH = 'OPENSEARCH', +} + +export const getActionApiDoc = (engine: EngineType, version: string, action: SearchAction) => { + const { APIS } = getDocLinks(engine, version); + const matchedAction = Object.entries(actionRegexMap).find(([, regex]: [ActionType, RegExp]) => + `${action.method} /${action.path}`.match(regex), + ); + + return matchedAction ? APIS[matchedAction[0] as ActionType] : undefined; +}; + +const getDocLinks = (engine: EngineType, version: string) => { + const DOCS_LINK = `https://www.elastic.co/guide/en/elasticsearch/reference/${version}`; + const linksMap: { + [key in EngineType]: { + APIS: { + [key in ActionType]: string; + }; + }; + } = { + [EngineType.ELASTICSEARCH]: { + APIS: { + POST_INDEX: `${DOCS_LINK}/indices-create-index.html`, + POST_SEARCH: `${DOCS_LINK}/search-search.html`, + POST_COUNT: `${DOCS_LINK}/search-count.html`, + GET_SEARCH: `${DOCS_LINK}/docs-get.html`, + POST_UPDATE: `${DOCS_LINK}/docs-update.html`, + DELETE_DOC: `${DOCS_LINK}/docs-delete.html`, + PUT_INDEX: `${DOCS_LINK}/indices-create-index.html`, + DELETE_INDEX: `${DOCS_LINK}/indices-delete-index.html`, + POST_BULK: `${DOCS_LINK}/docs-bulk.html`, + PUT_PUT_INDEX: `${DOCS_LINK}/indices-create-index.html`, + PUT_MAPPING: `${DOCS_LINK}/indices-put-mapping.html`, + GET_MAPPING: `${DOCS_LINK}/indices-get-mapping.html`, + POST_ALIAS: `${DOCS_LINK}/indices-aliases.html`, + GET_HEALTH: `${DOCS_LINK}/cluster-health.html`, + GET_STATE: `${DOCS_LINK}/indices-stats.html`, + GET_INFO: '', + HEAD_INDEX: `${DOCS_LINK}/indices-exists.html`, + PUT_AUTO_FOLLOW: `${DOCS_LINK}/ccr-put-auto-follow-pattern.html`, + PUT_CCR_FOLLOW: `${DOCS_LINK}/ccr-put-follow.html`, + PUT_SLM_POLICY: `${DOCS_LINK}/slm-api-put-policy.html`, + PUT_SECURITY_ROLE_MAPPING: `${DOCS_LINK}/security-api-put-role-mapping.html`, + PUT_ROLLUP_JOB: `${DOCS_LINK}/rollup-put-job.html#rollup-put-job-api-request-body`, + PUT_SECURITY_API_KEY: `${DOCS_LINK}/security-api-create-api-key.html`, + PUT_INGEST_PIPELINE: `${DOCS_LINK}/put-pipeline-api.html`, + PUT_TRANSFORM: `${DOCS_LINK}/put-transform.html#put-transform-request-body`, + POST_ML_INFER: `${DOCS_LINK}/infer-trained-model.html`, + POST_MULTI_SEARCH: `${DOCS_LINK}/search-multi-search.html`, + POST_OPEN_INDEX: `${DOCS_LINK}/indices-open-close.html`, + PUT_COMPONENT_TEMPLATE: `${DOCS_LINK}/indices-component-template.html`, + PUT_ENRICH_POLICY: `${DOCS_LINK}/put-enrich-policy-api.html`, + PUT_TEMPLATE: `${DOCS_LINK}/indices-templates-v1.html`, + }, + }, + // @TODO docs link for OpenSearch + [EngineType.OPENSEARCH]: { APIS: {} } as { APIS: { [key in ActionType]: string } }, + }; + + return linksMap[engine]; +}; diff --git a/src/electron/main.ts b/src/electron/main.ts index 5c52a5ec..f3fee230 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -102,6 +102,9 @@ app.on('activate', async () => { ipcMain.on('open-github', () => { shell.openExternal(githubLink); }); +ipcMain.on('open-link', (_event, link: string) => { + shell.openExternal(link); +}); registerStoreApiListener(ipcMain); registerSourceFileApiListener(ipcMain); diff --git a/src/electron/preload.ts b/src/electron/preload.ts index 65d6c9ca..732fb2a5 100644 --- a/src/electron/preload.ts +++ b/src/electron/preload.ts @@ -8,7 +8,9 @@ contextBridge.exposeInMainWorld('browserWindow', { contextBridge.exposeInMainWorld('electronAPI', { openGitHub: () => ipcRenderer.send('open-github'), + openLink: (link: string) => ipcRenderer.send('open-link', link), }); + contextBridge.exposeInMainWorld('storeAPI', { get: async (key: string, defaultValue: unknown) => ipcRenderer.invoke('storeAPI', { method: 'GET', key, value: defaultValue }), diff --git a/src/views/editor/index.vue b/src/views/editor/index.vue index 428dac9e..1ce53601 100644 --- a/src/views/editor/index.vue +++ b/src/views/editor/index.vue @@ -14,7 +14,9 @@ import { CustomError, Decoration, defaultCodeSnippet, - SearchToken, + EngineType, + getActionApiDoc, + SearchAction, searchTokensProvider, } from '../../common'; import { useAppStore, useConnectionStore, useSourceFileStore } from '../../store'; @@ -94,9 +96,9 @@ let autoIndentCmdId: string | null = null; const queryEditorRef = ref(); const displayEditorRef = ref(); -let searchTokens: SearchToken[] = []; +let searchTokens: SearchAction[] = []; -const getActionMarksDecorations = (searchTokens: SearchToken[]): Array => { +const getActionMarksDecorations = (searchTokens: SearchAction[]): Array => { return searchTokens .map(({ actionPosition }) => ({ id: actionPosition.startLineNumber, @@ -107,7 +109,7 @@ const getActionMarksDecorations = (searchTokens: SearchToken[]): Array (a as Decoration).id - (b as Decoration).id) as Array; }; -const refreshActionMarks = (editor: Editor, searchTokens: SearchToken[]) => { +const refreshActionMarks = (editor: Editor, searchTokens: SearchAction[]) => { const freshedDecorations = getActionMarksDecorations(searchTokens); // @See https://github.com/Microsoft/monaco-editor/issues/913#issuecomment-396537569 executeDecorations = editor.deltaDecorations( @@ -115,7 +117,7 @@ const refreshActionMarks = (editor: Editor, searchTokens: SearchToken[]) => { freshedDecorations, ) as unknown as Decoration[]; }; -const buildCodeLens = (searchTokens: SearchToken[]) => +const buildCodeLens = (searchTokens: SearchAction[]) => searchTokens .filter(({ qdslPosition }) => qdslPosition) .map(({ actionPosition, qdslPosition }, index) => ({ @@ -243,7 +245,7 @@ const autoIndentAction = ( } }; -const getPointerAction = (editor: Editor, tokens: Array) => { +const getPointerAction = (editor: Editor, tokens: Array) => { if (!editor) { return; } @@ -341,6 +343,18 @@ const setupQueryEditor = (code: string) => { queryEditor.trigger('keyboard', 'editor.foldAll', {}); queryEditor.trigger('keyboard', 'editor.unfoldRecursively', {}); }); + + // Open the documentation for the current action + queryEditor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Slash, () => { + const docLink = getActionApiDoc( + EngineType.ELASTICSEARCH, + 'current', + getPointerAction(queryEditor, searchTokens), + ); + if (docLink) { + window.electronAPI.openLink(docLink); + } + }); }; const setupJsonEditor = () => { displayEditor = monaco.editor.create(displayEditorRef.value, { diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 90f67571..e3da2025 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -13,6 +13,7 @@ declare module '*.css'; export interface IElectronAPI { openGitHub: () => void; + openLink: (link: string) => void; } export interface IStoreAPI { get: (key: string, defaultValue: T) => Promise;