ydb-embedded-ui 6.0.1 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/components/CriticalActionDialog/CriticalActionDialog.scss +0 -2
- package/dist/containers/PDiskPage/PDiskPage.js +6 -1
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +2 -1
- package/dist/containers/Tenant/Query/QueryEditor/helpers.js +4 -3
- package/dist/containers/Tenant/Tenant.js +1 -1
- package/dist/containers/UserSettings/i18n/en.json +2 -0
- package/dist/containers/UserSettings/i18n/index.d.ts +1 -1
- package/dist/containers/UserSettings/settings.d.ts +1 -0
- package/dist/containers/UserSettings/settings.js +7 -2
- package/dist/services/api.d.ts +9 -1
- package/dist/services/api.js +5 -0
- package/dist/services/settings.js +2 -1
- package/dist/types/api/autocomplete.d.ts +21 -0
- package/dist/types/api/autocomplete.js +1 -0
- package/dist/types/api/restartPDisk.d.ts +4 -0
- package/dist/types/api/restartPDisk.js +1 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +1 -0
- package/dist/utils/monaco/index.js +2 -0
- package/dist/utils/monaco/{yqlSuggestions → yql}/constants.d.ts +1 -0
- package/dist/utils/monaco/{yqlSuggestions → yql}/constants.js +1 -0
- package/dist/utils/monaco/{yqlSuggestions → yql}/generateSuggestions.d.ts +3 -3
- package/dist/utils/monaco/{yqlSuggestions → yql}/generateSuggestions.js +124 -64
- package/dist/utils/monaco/yql/registerLanguage.d.ts +1 -0
- package/dist/utils/monaco/yql/registerLanguage.js +8 -0
- package/dist/utils/monaco/{yqlSuggestions/registerCompletionItemProvider.js → yql/yql.completionItemProvider.js} +3 -2
- package/dist/utils/monaco/yql/yql.d.ts +7 -0
- package/dist/utils/monaco/yql/yql.js +180 -0
- package/dist/utils/monaco/yql/yql.keywords.d.ts +3 -0
- package/dist/utils/monaco/yql/yql.keywords.js +3 -0
- package/dist/utils/monaco/{yqlSuggestions → yql}/yqlSuggestions.js +14 -7
- package/package.json +3 -3
- /package/dist/utils/monaco/{yqlSuggestions/registerCompletionItemProvider.d.ts → yql/yql.completionItemProvider.d.ts} +0 -0
- /package/dist/utils/monaco/{yqlSuggestions → yql}/yqlSuggestions.d.ts +0 -0
@@ -46,7 +46,12 @@ export function PDiskPage() {
|
|
46
46
|
const groupsData = (_a = pDiskStorageQuery.currentData) !== null && _a !== void 0 ? _a : [];
|
47
47
|
const handleRestart = async () => {
|
48
48
|
if (valueIsDefined(nodeId) && valueIsDefined(pDiskId)) {
|
49
|
-
return window.api.restartPDisk(nodeId, pDiskId)
|
49
|
+
return window.api.restartPDisk(nodeId, pDiskId).then((res) => {
|
50
|
+
if ((res === null || res === void 0 ? void 0 : res.result) === false) {
|
51
|
+
const err = { statusText: res.error };
|
52
|
+
throw err;
|
53
|
+
}
|
54
|
+
});
|
50
55
|
}
|
51
56
|
return undefined;
|
52
57
|
};
|
@@ -10,6 +10,7 @@ import { setShowPreview } from '../../../../store/reducers/schema/schema';
|
|
10
10
|
import { cn } from '../../../../utils/cn';
|
11
11
|
import { DEFAULT_IS_QUERY_RESULT_COLLAPSED, DEFAULT_SIZE_RESULT_PANE_KEY, LAST_USED_QUERY_ACTION_KEY, QUERY_USE_MULTI_SCHEMA_KEY, SAVED_QUERIES_KEY, } from '../../../../utils/constants';
|
12
12
|
import { useQueryModes, useSetting } from '../../../../utils/hooks';
|
13
|
+
import { LANGUAGE_YQL_ID } from '../../../../utils/monaco/yql/constants';
|
13
14
|
import { QUERY_ACTIONS } from '../../../../utils/query';
|
14
15
|
import { parseJson } from '../../../../utils/utils';
|
15
16
|
import { PaneVisibilityActionTypes, paneVisibilityToggleReducerCreator, } from '../../utils/paneVisibilityToggleHelpers';
|
@@ -286,7 +287,7 @@ function QueryEditor(props) {
|
|
286
287
|
};
|
287
288
|
return (_jsx("div", { className: b(), children: _jsxs(SplitPane, { direction: "vertical", defaultSizePaneKey: DEFAULT_SIZE_RESULT_PANE_KEY, triggerCollapse: resultVisibilityState.triggerCollapse, triggerExpand: resultVisibilityState.triggerExpand, minSize: [0, 52], collapsedSizes: [100, 0], onSplitStartDragAdditional: onSplitStartDragAdditional, children: [_jsxs("div", { className: b('pane-wrapper', {
|
288
289
|
top: true,
|
289
|
-
}), children: [_jsx("div", { className: b('monaco-wrapper'), children: _jsx("div", { className: b('monaco'), children: _jsx(MonacoEditor, { language:
|
290
|
+
}), children: [_jsx("div", { className: b('monaco-wrapper'), children: _jsx("div", { className: b('monaco'), children: _jsx(MonacoEditor, { language: LANGUAGE_YQL_ID, value: executeQuery.input, options: editorOptions, onChange: onChange, editorDidMount: editorDidMount, theme: `vs-${theme}` }) }) }), renderControls()] }), _jsx("div", { className: b('pane-wrapper'), children: _jsx(Result, { executeQuery: executeQuery, explainQuery: explainQuery, resultVisibilityState: resultVisibilityState, onExpandResultHandler: onExpandResultHandler, onCollapseResultHandler: onCollapseResultHandler, type: type, handleAstQuery: handleAstQuery, theme: theme, resultType: resultType, path: path, showPreview: showPreview }) })] }) }));
|
290
291
|
}
|
291
292
|
const mapStateToProps = (state) => {
|
292
293
|
return {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { ENABLE_AUTOCOMPLETE, useSetting } from '../../../../lib';
|
2
|
+
import { AUTOCOMPLETE_ON_ENTER, ENABLE_AUTOCOMPLETE, useSetting } from '../../../../lib';
|
3
3
|
export const EDITOR_OPTIONS = {
|
4
4
|
automaticLayout: true,
|
5
5
|
selectOnLineNumbers: true,
|
@@ -9,9 +9,10 @@ export const EDITOR_OPTIONS = {
|
|
9
9
|
};
|
10
10
|
export function useEditorOptions() {
|
11
11
|
const [enableAutocomplete] = useSetting(ENABLE_AUTOCOMPLETE);
|
12
|
+
const [autocompleteOnEnter] = useSetting(AUTOCOMPLETE_ON_ENTER);
|
12
13
|
const options = React.useMemo(() => {
|
13
14
|
const useAutocomplete = Boolean(enableAutocomplete);
|
14
|
-
return Object.assign({ quickSuggestions: useAutocomplete, suggestOnTriggerCharacters: useAutocomplete }, EDITOR_OPTIONS);
|
15
|
-
}, [enableAutocomplete]);
|
15
|
+
return Object.assign({ quickSuggestions: useAutocomplete, suggestOnTriggerCharacters: useAutocomplete, acceptSuggestionOnEnter: autocompleteOnEnter ? 'on' : 'off' }, EDITOR_OPTIONS);
|
16
|
+
}, [enableAutocomplete, autocompleteOnEnter]);
|
16
17
|
return options;
|
17
18
|
}
|
@@ -47,7 +47,7 @@ function Tenant(props) {
|
|
47
47
|
React.useEffect(() => {
|
48
48
|
if (tenantName && typeof tenantName === 'string' && previousTenant.current !== tenantName) {
|
49
49
|
const register = async () => {
|
50
|
-
const { registerYQLCompletionItemProvider } = await import('../../utils/monaco/
|
50
|
+
const { registerYQLCompletionItemProvider } = await import('../../utils/monaco/yql/yql.completionItemProvider');
|
51
51
|
registerYQLCompletionItemProvider(tenantName);
|
52
52
|
};
|
53
53
|
register().catch(console.error);
|
@@ -7,6 +7,8 @@
|
|
7
7
|
"section.dev-setting": "Development settings",
|
8
8
|
"settings.editor.autocomplete.title": "Enable autocomplete",
|
9
9
|
"settings.editor.autocomplete.description": "You’re always able to get suggestions by pressing Ctrl+Space.",
|
10
|
+
"settings.editor.autocomplete-on-enter.title": "Accept suggestion on Enter",
|
11
|
+
"settings.editor.autocomplete-on-enter.description": "Controls whether suggestions should be accepted on Enter, in addition to Tab. Helps to avoid ambiguity between inserting new lines or accepting suggestions.",
|
10
12
|
"settings.theme.title": "Interface theme",
|
11
13
|
"settings.theme.option-dark": "Dark",
|
12
14
|
"settings.theme.option-light": "Light",
|
@@ -1,2 +1,2 @@
|
|
1
|
-
declare const _default: (key: "page.general" | "section.appearance" | "page.experiments" | "section.experiments" | "page.editor" | "section.dev-setting" | "settings.editor.autocomplete.title" | "settings.editor.autocomplete.description" | "settings.theme.title" | "settings.theme.option-dark" | "settings.theme.option-light" | "settings.theme.option-system" | "settings.language.title" | "settings.language.option-russian" | "settings.language.option-english" | "settings.binaryDataInPlainTextDisplay.title" | "settings.binaryDataInPlainTextDisplay.description" | "settings.invertedDisks.title" | "settings.useNodesEndpoint.title" | "settings.useNodesEndpoint.popover" | "settings.useVirtualTables.title" | "settings.useVirtualTables.popover" | "settings.queryUseMultiSchema.title" | "settings.queryUseMultiSchema.popover", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
1
|
+
declare const _default: (key: "page.general" | "section.appearance" | "page.experiments" | "section.experiments" | "page.editor" | "section.dev-setting" | "settings.editor.autocomplete.title" | "settings.editor.autocomplete.description" | "settings.editor.autocomplete-on-enter.title" | "settings.editor.autocomplete-on-enter.description" | "settings.theme.title" | "settings.theme.option-dark" | "settings.theme.option-light" | "settings.theme.option-system" | "settings.language.title" | "settings.language.option-russian" | "settings.language.option-english" | "settings.binaryDataInPlainTextDisplay.title" | "settings.binaryDataInPlainTextDisplay.description" | "settings.invertedDisks.title" | "settings.useNodesEndpoint.title" | "settings.useNodesEndpoint.popover" | "settings.useVirtualTables.title" | "settings.useVirtualTables.popover" | "settings.queryUseMultiSchema.title" | "settings.queryUseMultiSchema.popover", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
2
2
|
export default _default;
|
@@ -20,6 +20,7 @@ export declare const useNodesEndpointSetting: SettingProps;
|
|
20
20
|
export declare const useVirtualTables: SettingProps;
|
21
21
|
export declare const queryUseMultiSchemaSetting: SettingProps;
|
22
22
|
export declare const enableAutocompleteSetting: SettingProps;
|
23
|
+
export declare const autocompleteOnEnterSetting: SettingProps;
|
23
24
|
export declare const appearanceSection: SettingsSection;
|
24
25
|
export declare const experimentsSection: SettingsSection;
|
25
26
|
export declare const devSettingsSection: SettingsSection;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import { Flask, PencilToSquare, StarFill } from '@gravity-ui/icons';
|
3
|
-
import { BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, ENABLE_AUTOCOMPLETE, INVERTED_DISKS_KEY, LANGUAGE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, } from '../../utils/constants';
|
3
|
+
import { AUTOCOMPLETE_ON_ENTER, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, ENABLE_AUTOCOMPLETE, INVERTED_DISKS_KEY, LANGUAGE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, } from '../../utils/constants';
|
4
4
|
import { Lang, defaultLang } from '../../utils/i18n';
|
5
5
|
import { ClusterModeGuard } from '../ClusterModeGuard';
|
6
6
|
import i18n from './i18n';
|
@@ -73,6 +73,11 @@ export const enableAutocompleteSetting = {
|
|
73
73
|
title: i18n('settings.editor.autocomplete.title'),
|
74
74
|
description: i18n('settings.editor.autocomplete.description'),
|
75
75
|
};
|
76
|
+
export const autocompleteOnEnterSetting = {
|
77
|
+
settingKey: AUTOCOMPLETE_ON_ENTER,
|
78
|
+
title: i18n('settings.editor.autocomplete-on-enter.title'),
|
79
|
+
description: i18n('settings.editor.autocomplete-on-enter.description'),
|
80
|
+
};
|
76
81
|
export const appearanceSection = {
|
77
82
|
id: 'appearanceSection',
|
78
83
|
title: i18n('section.appearance'),
|
@@ -86,7 +91,7 @@ export const experimentsSection = {
|
|
86
91
|
export const devSettingsSection = {
|
87
92
|
id: 'devSettingsSection',
|
88
93
|
title: i18n('section.dev-setting'),
|
89
|
-
settings: [enableAutocompleteSetting],
|
94
|
+
settings: [enableAutocompleteSetting, autocompleteOnEnterSetting],
|
90
95
|
};
|
91
96
|
export const generalPage = {
|
92
97
|
id: 'generalPage',
|
package/dist/services/api.d.ts
CHANGED
@@ -2,6 +2,7 @@ import AxiosWrapper from '@gravity-ui/axios-wrapper';
|
|
2
2
|
import type { ComputeApiRequestParams, NodesApiRequestParams } from '../store/reducers/nodes/types';
|
3
3
|
import type { StorageApiRequestParams } from '../store/reducers/storage/types';
|
4
4
|
import type { TMetaInfo } from '../types/api/acl';
|
5
|
+
import type { TQueryAutocomplete } from '../types/api/autocomplete';
|
5
6
|
import type { TClusterInfo } from '../types/api/cluster';
|
6
7
|
import type { TComputeInfo } from '../types/api/compute';
|
7
8
|
import type { DescribeConsumerResult } from '../types/api/consumer';
|
@@ -14,6 +15,7 @@ import type { TEvNodesInfo } from '../types/api/nodesList';
|
|
14
15
|
import type { TEvPDiskStateResponse } from '../types/api/pdisk';
|
15
16
|
import type { Actions, ExplainActions, ExplainResponse, QueryAPIResponse, Schemas } from '../types/api/query';
|
16
17
|
import type { JsonRenderRequestParams, JsonRenderResponse } from '../types/api/render';
|
18
|
+
import type { RestartPDiskResponse } from '../types/api/restartPDisk';
|
17
19
|
import type { TEvDescribeSchemeResult } from '../types/api/schema';
|
18
20
|
import type { TStorageInfo } from '../types/api/storage';
|
19
21
|
import type { TEvSystemStateResponse } from '../types/api/systemState';
|
@@ -104,7 +106,7 @@ export declare class YdbEmbeddedAPI extends AxiosWrapper {
|
|
104
106
|
failDomainIdx: string | number;
|
105
107
|
vDiskIdx: string | number;
|
106
108
|
}): Promise<any>;
|
107
|
-
restartPDisk(nodeId: number | string, pDiskId: number | string): Promise<
|
109
|
+
restartPDisk(nodeId: number | string, pDiskId: number | string): Promise<RestartPDiskResponse>;
|
108
110
|
killTablet(id?: string): Promise<string>;
|
109
111
|
stopTablet(id?: string, hiveId?: string): Promise<string>;
|
110
112
|
resumeTablet(id?: string, hiveId?: string): Promise<string>;
|
@@ -115,6 +117,12 @@ export declare class YdbEmbeddedAPI extends AxiosWrapper {
|
|
115
117
|
authenticate(user: string, password: string): Promise<any>;
|
116
118
|
logout(): Promise<any>;
|
117
119
|
whoami(): Promise<TUserToken>;
|
120
|
+
autocomplete(params: {
|
121
|
+
database: string;
|
122
|
+
prefix?: string;
|
123
|
+
limit?: number;
|
124
|
+
table?: string[];
|
125
|
+
}): Promise<TQueryAutocomplete>;
|
118
126
|
getClustersList(_?: never, { signal }?: {
|
119
127
|
signal?: AbortSignal;
|
120
128
|
}): Promise<MetaClusters>;
|
package/dist/services/api.js
CHANGED
@@ -302,6 +302,11 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
302
302
|
whoami() {
|
303
303
|
return this.get(this.getPath('/viewer/json/whoami'), {});
|
304
304
|
}
|
305
|
+
autocomplete(params) {
|
306
|
+
const { table } = params, rest = __rest(params, ["table"]);
|
307
|
+
const tablesParam = table === null || table === void 0 ? void 0 : table.join(',');
|
308
|
+
return this.get(this.getPath('/viewer/json/autocomplete'), Object.assign(Object.assign({}, rest), { table: tablesParam }), { concurrentId: 'sql-autocomplete' });
|
309
|
+
}
|
305
310
|
// used if not single cluster mode
|
306
311
|
getClustersList(_, { signal } = {}) {
|
307
312
|
return this.get(`${META_BACKEND || ''}/meta/clusters`, null, {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { TENANT_PAGES_IDS } from '../store/reducers/tenant/constants';
|
2
|
-
import { ASIDE_HEADER_COMPACT_KEY, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, ENABLE_AUTOCOMPLETE, INVERTED_DISKS_KEY, LANGUAGE_KEY, LAST_USED_QUERY_ACTION_KEY, PARTITIONS_HIDDEN_COLUMNS_KEY, QUERY_INITIAL_MODE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, SAVED_QUERIES_KEY, TENANT_INITIAL_PAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_CLUSTER_BALANCER_AS_BACKEND_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, } from '../utils/constants';
|
2
|
+
import { ASIDE_HEADER_COMPACT_KEY, AUTOCOMPLETE_ON_ENTER, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, ENABLE_AUTOCOMPLETE, INVERTED_DISKS_KEY, LANGUAGE_KEY, LAST_USED_QUERY_ACTION_KEY, PARTITIONS_HIDDEN_COLUMNS_KEY, QUERY_INITIAL_MODE_KEY, QUERY_USE_MULTI_SCHEMA_KEY, SAVED_QUERIES_KEY, TENANT_INITIAL_PAGE_KEY, THEME_KEY, USE_BACKEND_PARAMS_FOR_TABLES_KEY, USE_CLUSTER_BALANCER_AS_BACKEND_KEY, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, } from '../utils/constants';
|
3
3
|
import { QUERY_ACTIONS, QUERY_MODES } from '../utils/query';
|
4
4
|
import { parseJson } from '../utils/utils';
|
5
5
|
/** User settings keys and their default values */
|
@@ -19,6 +19,7 @@ export const DEFAULT_USER_SETTINGS = {
|
|
19
19
|
[USE_BACKEND_PARAMS_FOR_TABLES_KEY]: false,
|
20
20
|
[USE_CLUSTER_BALANCER_AS_BACKEND_KEY]: true,
|
21
21
|
[ENABLE_AUTOCOMPLETE]: false,
|
22
|
+
[AUTOCOMPLETE_ON_ENTER]: true,
|
22
23
|
};
|
23
24
|
class SettingsManager {
|
24
25
|
constructor() {
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/**
|
2
|
+
* endpoint: /viewer/json/autocomplete
|
3
|
+
*
|
4
|
+
* source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/protos/viewer.proto
|
5
|
+
*/
|
6
|
+
export interface TQueryAutocomplete {
|
7
|
+
Success: boolean;
|
8
|
+
Error?: string[];
|
9
|
+
Result: TAutocompleteResult;
|
10
|
+
}
|
11
|
+
interface TAutocompleteResult {
|
12
|
+
Entities: TAutocompleteEntity[];
|
13
|
+
Total?: number;
|
14
|
+
}
|
15
|
+
export interface TAutocompleteEntity {
|
16
|
+
Name: string;
|
17
|
+
Type: AutocompleteEntityType;
|
18
|
+
Parent: string;
|
19
|
+
}
|
20
|
+
export type AutocompleteEntityType = 'unknown' | 'dir' | 'table' | 'pers_queue_group' | 'sub_domain' | 'rtmr_volume' | 'block_store_volume' | 'kesus' | 'solomon_volume' | 'table_index' | 'ext_sub_domain' | 'file_store' | 'column_store' | 'column_table' | 'cdc_stream' | 'sequence' | 'replication' | 'blob_depot' | 'external_table' | 'external_data_source' | 'view' | 'column' | 'index';
|
21
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -88,3 +88,4 @@ export declare const USE_BACKEND_PARAMS_FOR_TABLES_KEY = "useBackendParamsForTab
|
|
88
88
|
export declare const QUERY_USE_MULTI_SCHEMA_KEY = "queryUseMultiSchema";
|
89
89
|
export declare const USE_CLUSTER_BALANCER_AS_BACKEND_KEY = "useClusterBalancerAsBacked";
|
90
90
|
export declare const ENABLE_AUTOCOMPLETE = "enableAutocomplete";
|
91
|
+
export declare const AUTOCOMPLETE_ON_ENTER = "autocompleteOnEnter";
|
package/dist/utils/constants.js
CHANGED
@@ -101,3 +101,4 @@ export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
|
|
101
101
|
export const QUERY_USE_MULTI_SCHEMA_KEY = 'queryUseMultiSchema';
|
102
102
|
export const USE_CLUSTER_BALANCER_AS_BACKEND_KEY = 'useClusterBalancerAsBacked';
|
103
103
|
export const ENABLE_AUTOCOMPLETE = 'enableAutocomplete';
|
104
|
+
export const AUTOCOMPLETE_ON_ENTER = 'autocompleteOnEnter';
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import type { ColumnAliasSuggestion, KeywordSuggestion, YqlAutocompleteResult } from '@gravity-ui/websql-autocomplete';
|
2
|
-
import
|
1
|
+
import type { ColumnAliasSuggestion, KeywordSuggestion, YQLEntity, YqlAutocompleteResult } from '@gravity-ui/websql-autocomplete';
|
2
|
+
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
3
3
|
export declare function generateColumnsSuggestion(rangeToInsertSuggestion: monaco.IRange, suggestColumns: YqlAutocompleteResult['suggestColumns'] | undefined, database: string): Promise<monaco.languages.CompletionItem[]>;
|
4
4
|
export declare function generateColumnAliasesSuggestion(rangeToInsertSuggestion: monaco.IRange, suggestColumnAliases?: ColumnAliasSuggestion[]): {
|
5
5
|
label: string;
|
@@ -17,7 +17,7 @@ export declare function generateKeywordsSuggestion(rangeToInsertSuggestion: mona
|
|
17
17
|
range: monaco.IRange;
|
18
18
|
sortText: string;
|
19
19
|
}[];
|
20
|
-
export declare function generateEntitiesSuggestion(
|
20
|
+
export declare function generateEntitiesSuggestion(rangeToInsertSuggestion: monaco.IRange, suggestEntities: YQLEntity[], database: string, prefix?: string): Promise<monaco.languages.CompletionItem[]>;
|
21
21
|
export declare function generateSimpleFunctionsSuggestion(rangeToInsertSuggestion: monaco.IRange): Promise<monaco.languages.CompletionItem[]>;
|
22
22
|
export declare function generateSimpleTypesSuggestion(rangeToInsertSuggestion: monaco.IRange): Promise<monaco.languages.CompletionItem[]>;
|
23
23
|
export declare function generateUdfSuggestion(rangeToInsertSuggestion: monaco.IRange): Promise<monaco.languages.CompletionItem[]>;
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
1
2
|
import { AggregateFunctions, Pragmas, SimpleFunctions, SimpleTypes, TableFunction, Udfs, WindowFunctions, } from './constants';
|
2
3
|
const CompletionItemKind = {
|
3
4
|
Method: 0,
|
@@ -30,6 +31,27 @@ const CompletionItemKind = {
|
|
30
31
|
Snippet: 27,
|
31
32
|
};
|
32
33
|
const re = /[\s'"-/@]/;
|
34
|
+
const suggestionEntityToAutocomplete = {
|
35
|
+
externalDataSource: ['external_data_source'],
|
36
|
+
replication: ['replication'],
|
37
|
+
table: ['table'],
|
38
|
+
tableStore: ['column_store'],
|
39
|
+
topic: ['pers_queue_group'],
|
40
|
+
view: ['view'],
|
41
|
+
//TODO: add after websql-autocomplete support indexex
|
42
|
+
// index: ['table_index', 'index'],
|
43
|
+
};
|
44
|
+
const commonSuggestionEntities = ['dir', 'unknown'];
|
45
|
+
function filterAutocompleteEntities(autocompleteEntities, suggestions) {
|
46
|
+
const suggestionsSet = suggestions.reduce((acc, el) => {
|
47
|
+
const autocompleteEntity = suggestionEntityToAutocomplete[el];
|
48
|
+
if (autocompleteEntity) {
|
49
|
+
autocompleteEntity.forEach((el) => acc.add(el));
|
50
|
+
}
|
51
|
+
return acc;
|
52
|
+
}, new Set(commonSuggestionEntities));
|
53
|
+
return autocompleteEntities.filter(({ Type }) => suggestionsSet.has(Type));
|
54
|
+
}
|
33
55
|
function wrapStringToBackticks(value) {
|
34
56
|
let result = value;
|
35
57
|
if (value.match(re)) {
|
@@ -38,11 +60,29 @@ function wrapStringToBackticks(value) {
|
|
38
60
|
return result;
|
39
61
|
}
|
40
62
|
function removeBackticks(value) {
|
41
|
-
let
|
63
|
+
let sliceStart = 0;
|
64
|
+
let sliceEnd = value.length;
|
42
65
|
if (value.startsWith('`')) {
|
43
|
-
|
66
|
+
sliceStart = 1;
|
67
|
+
}
|
68
|
+
if (value.endsWith('`')) {
|
69
|
+
sliceEnd = -1;
|
70
|
+
}
|
71
|
+
return value.slice(sliceStart, sliceEnd);
|
72
|
+
}
|
73
|
+
function removeStartSlash(value) {
|
74
|
+
if (value.startsWith('/')) {
|
75
|
+
return value.slice(1);
|
76
|
+
}
|
77
|
+
return value;
|
78
|
+
}
|
79
|
+
function normalizeEntityPrefix(value = '', database) {
|
80
|
+
let cleanedValue = removeStartSlash(removeBackticks(value));
|
81
|
+
const cleanedDatabase = removeStartSlash(database);
|
82
|
+
if (cleanedValue.startsWith(cleanedDatabase)) {
|
83
|
+
cleanedValue = cleanedValue.slice(cleanedDatabase.length);
|
44
84
|
}
|
45
|
-
return
|
85
|
+
return removeStartSlash(cleanedValue);
|
46
86
|
}
|
47
87
|
const SuggestionsWeight = {
|
48
88
|
suggestTemplates: 0,
|
@@ -58,50 +98,6 @@ const SuggestionsWeight = {
|
|
58
98
|
suggestUdfs: 10,
|
59
99
|
suggestSimpleTypes: 11,
|
60
100
|
};
|
61
|
-
const KEEP_CACHE_MILLIS = 5 * 60 * 1000;
|
62
|
-
function getColumnsWithCache() {
|
63
|
-
const cache = new Map();
|
64
|
-
return async (path) => {
|
65
|
-
var _a, _b, _c, _d;
|
66
|
-
const normalizedPath = removeBackticks(path);
|
67
|
-
const existed = cache.get(path);
|
68
|
-
if (existed) {
|
69
|
-
return existed;
|
70
|
-
}
|
71
|
-
const columns = [];
|
72
|
-
const data = await window.api.getDescribe({ path: normalizedPath });
|
73
|
-
if ((data === null || data === void 0 ? void 0 : data.Status) === 'StatusSuccess') {
|
74
|
-
const desc = data.PathDescription;
|
75
|
-
if ((_a = desc === null || desc === void 0 ? void 0 : desc.Table) === null || _a === void 0 ? void 0 : _a.Columns) {
|
76
|
-
for (const c of desc.Table.Columns) {
|
77
|
-
if (c.Name) {
|
78
|
-
columns.push(c.Name);
|
79
|
-
}
|
80
|
-
}
|
81
|
-
}
|
82
|
-
if ((_c = (_b = desc === null || desc === void 0 ? void 0 : desc.ColumnTableDescription) === null || _b === void 0 ? void 0 : _b.Schema) === null || _c === void 0 ? void 0 : _c.Columns) {
|
83
|
-
for (const c of desc.ColumnTableDescription.Schema.Columns) {
|
84
|
-
if (c.Name) {
|
85
|
-
columns.push(c.Name);
|
86
|
-
}
|
87
|
-
}
|
88
|
-
}
|
89
|
-
if ((_d = desc === null || desc === void 0 ? void 0 : desc.ExternalTableDescription) === null || _d === void 0 ? void 0 : _d.Columns) {
|
90
|
-
for (const c of desc.ExternalTableDescription.Columns) {
|
91
|
-
if (c.Name) {
|
92
|
-
columns.push(c.Name);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}
|
96
|
-
}
|
97
|
-
cache.set(path, columns);
|
98
|
-
setTimeout(() => {
|
99
|
-
cache.delete(path);
|
100
|
-
}, KEEP_CACHE_MILLIS);
|
101
|
-
return columns;
|
102
|
-
};
|
103
|
-
}
|
104
|
-
const getColumns = getColumnsWithCache();
|
105
101
|
function getSuggestionIndex(suggestionType) {
|
106
102
|
return SuggestionsWeight[suggestionType];
|
107
103
|
}
|
@@ -127,28 +123,63 @@ async function getSimpleTypes() {
|
|
127
123
|
return SimpleTypes;
|
128
124
|
}
|
129
125
|
export async function generateColumnsSuggestion(rangeToInsertSuggestion, suggestColumns, database) {
|
130
|
-
var _a;
|
126
|
+
var _a, _b, _c;
|
131
127
|
if (!(suggestColumns === null || suggestColumns === void 0 ? void 0 : suggestColumns.tables)) {
|
132
128
|
return [];
|
133
129
|
}
|
134
130
|
const suggestions = [];
|
135
131
|
const multi = suggestColumns.tables.length > 1;
|
136
|
-
|
132
|
+
const normalizedTableNames = (_b = (_a = suggestColumns.tables) === null || _a === void 0 ? void 0 : _a.map((entity) => {
|
137
133
|
let normalizedEntityName = removeBackticks(entity.name);
|
138
|
-
|
139
|
-
|
140
|
-
normalizedEntityName = `${database}/${normalizedEntityName}`;
|
134
|
+
if (!normalizedEntityName.endsWith('/')) {
|
135
|
+
normalizedEntityName = `${normalizedEntityName}/`;
|
141
136
|
}
|
142
|
-
|
143
|
-
|
144
|
-
|
137
|
+
return normalizeEntityPrefix(normalizedEntityName, database);
|
138
|
+
})) !== null && _b !== void 0 ? _b : [];
|
139
|
+
// remove duplicates if any
|
140
|
+
const filteredTableNames = Array.from(new Set(normalizedTableNames));
|
141
|
+
const autocompleteResponse = await window.api.autocomplete({
|
142
|
+
database,
|
143
|
+
table: filteredTableNames,
|
144
|
+
limit: 1000,
|
145
|
+
});
|
146
|
+
if (!autocompleteResponse.Success) {
|
147
|
+
return [];
|
148
|
+
}
|
149
|
+
const tableNameToAliasMap = (_c = suggestColumns.tables) === null || _c === void 0 ? void 0 : _c.reduce((acc, entity) => {
|
150
|
+
var _a;
|
151
|
+
const normalizedEntityName = normalizeEntityPrefix(removeBackticks(entity.name), database);
|
152
|
+
const aliases = (_a = acc[normalizedEntityName]) !== null && _a !== void 0 ? _a : [];
|
153
|
+
if (entity.alias) {
|
154
|
+
aliases.push(entity.alias);
|
155
|
+
}
|
156
|
+
acc[normalizedEntityName] = aliases;
|
157
|
+
return acc;
|
158
|
+
}, {});
|
159
|
+
autocompleteResponse.Result.Entities.forEach((col) => {
|
160
|
+
if (col.Type !== 'column') {
|
161
|
+
return;
|
162
|
+
}
|
163
|
+
const normalizedName = wrapStringToBackticks(col.Name);
|
164
|
+
const normalizedParentName = normalizeEntityPrefix(col.Parent, database);
|
165
|
+
const aliases = tableNameToAliasMap[normalizedParentName];
|
166
|
+
if (aliases === null || aliases === void 0 ? void 0 : aliases.length) {
|
167
|
+
aliases.forEach((a) => {
|
168
|
+
const columnNameSuggestion = `${a}.${normalizedName}`;
|
169
|
+
suggestions.push({
|
170
|
+
label: columnNameSuggestion,
|
171
|
+
insertText: columnNameSuggestion,
|
172
|
+
kind: CompletionItemKind.Field,
|
173
|
+
detail: 'Column',
|
174
|
+
range: rangeToInsertSuggestion,
|
175
|
+
sortText: suggestionIndexToWeight(getSuggestionIndex('suggestColumns')),
|
176
|
+
});
|
177
|
+
});
|
178
|
+
}
|
179
|
+
else {
|
145
180
|
let columnNameSuggestion = normalizedName;
|
146
|
-
if (
|
147
|
-
columnNameSuggestion = `${
|
148
|
-
}
|
149
|
-
else if (multi) {
|
150
|
-
// no need to wrap entity.name to backticks, because it's already with them if needed
|
151
|
-
columnNameSuggestion = `${entity.name}.${normalizedName}`;
|
181
|
+
if (multi) {
|
182
|
+
columnNameSuggestion = `${wrapStringToBackticks(normalizedParentName)}.${normalizedName}`;
|
152
183
|
}
|
153
184
|
suggestions.push({
|
154
185
|
label: columnNameSuggestion,
|
@@ -158,8 +189,8 @@ export async function generateColumnsSuggestion(rangeToInsertSuggestion, suggest
|
|
158
189
|
range: rangeToInsertSuggestion,
|
159
190
|
sortText: suggestionIndexToWeight(getSuggestionIndex('suggestColumns')),
|
160
191
|
});
|
161
|
-
}
|
162
|
-
}
|
192
|
+
}
|
193
|
+
});
|
163
194
|
return suggestions;
|
164
195
|
}
|
165
196
|
export function generateColumnAliasesSuggestion(rangeToInsertSuggestion, suggestColumnAliases) {
|
@@ -188,7 +219,36 @@ export function generateKeywordsSuggestion(rangeToInsertSuggestion, suggestKeywo
|
|
188
219
|
sortText: suggestionIndexToWeight(getSuggestionIndex('suggestKeywords')),
|
189
220
|
}));
|
190
221
|
}
|
191
|
-
export async function generateEntitiesSuggestion(
|
222
|
+
export async function generateEntitiesSuggestion(rangeToInsertSuggestion, suggestEntities, database, prefix) {
|
223
|
+
const normalizedPrefix = normalizeEntityPrefix(prefix, database);
|
224
|
+
const data = await window.api.autocomplete({ database, prefix: normalizedPrefix, limit: 1000 });
|
225
|
+
const withBackticks = prefix === null || prefix === void 0 ? void 0 : prefix.startsWith('`');
|
226
|
+
if (data.Success) {
|
227
|
+
const filteredEntities = filterAutocompleteEntities(data.Result.Entities, suggestEntities);
|
228
|
+
return filteredEntities.reduce((acc, { Name, Type }) => {
|
229
|
+
const isDir = Type === 'dir';
|
230
|
+
const label = isDir ? `${Name}/` : Name;
|
231
|
+
let labelAsSnippet;
|
232
|
+
if (isDir && !withBackticks) {
|
233
|
+
labelAsSnippet = `\`${label}$0\``;
|
234
|
+
}
|
235
|
+
acc.push({
|
236
|
+
label,
|
237
|
+
insertText: labelAsSnippet !== null && labelAsSnippet !== void 0 ? labelAsSnippet : label,
|
238
|
+
kind: isDir ? CompletionItemKind.Folder : CompletionItemKind.Text,
|
239
|
+
insertTextRules: labelAsSnippet
|
240
|
+
? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
241
|
+
: monaco.languages.CompletionItemInsertTextRule.None,
|
242
|
+
detail: Type,
|
243
|
+
range: rangeToInsertSuggestion,
|
244
|
+
command: label.endsWith('/')
|
245
|
+
? { id: 'editor.action.triggerSuggest', title: '' }
|
246
|
+
: undefined,
|
247
|
+
sortText: suggestionIndexToWeight(getSuggestionIndex('suggestEntity')),
|
248
|
+
});
|
249
|
+
return acc;
|
250
|
+
}, []);
|
251
|
+
}
|
192
252
|
return [];
|
193
253
|
}
|
194
254
|
export async function generateSimpleFunctionsSuggestion(rangeToInsertSuggestion) {
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function registerYqlLanguage(): void;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import * as monaco from 'monaco-editor';
|
2
|
+
import { LANGUAGE_YQL_ID } from './constants';
|
3
|
+
import { conf, getLanguage } from './yql';
|
4
|
+
export function registerYqlLanguage() {
|
5
|
+
monaco.languages.register({ id: LANGUAGE_YQL_ID });
|
6
|
+
monaco.languages.setMonarchTokensProvider(LANGUAGE_YQL_ID, getLanguage());
|
7
|
+
monaco.languages.setLanguageConfiguration(LANGUAGE_YQL_ID, conf);
|
8
|
+
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import * as monaco from 'monaco-editor';
|
2
|
+
import { LANGUAGE_YQL_ID } from './constants';
|
2
3
|
import { createProvideSuggestionsFunction } from './yqlSuggestions';
|
3
4
|
let completionProvider;
|
4
5
|
function disableCodeSuggestions() {
|
@@ -8,8 +9,8 @@ function disableCodeSuggestions() {
|
|
8
9
|
}
|
9
10
|
export function registerYQLCompletionItemProvider(database) {
|
10
11
|
disableCodeSuggestions();
|
11
|
-
completionProvider = monaco.languages.registerCompletionItemProvider(
|
12
|
-
triggerCharacters: [' ', '
|
12
|
+
completionProvider = monaco.languages.registerCompletionItemProvider(LANGUAGE_YQL_ID, {
|
13
|
+
triggerCharacters: [' ', '', ',', '.', '`', '(', '/'],
|
13
14
|
provideCompletionItems: createProvideSuggestionsFunction(database),
|
14
15
|
});
|
15
16
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import type * as monaco from 'monaco-editor';
|
2
|
+
export declare const conf: monaco.languages.LanguageConfiguration;
|
3
|
+
interface LanguageOptions {
|
4
|
+
ansi?: boolean;
|
5
|
+
}
|
6
|
+
export declare function getLanguage({ ansi, }?: LanguageOptions): monaco.languages.IMonarchLanguage & Record<string, unknown>;
|
7
|
+
export {};
|
@@ -0,0 +1,180 @@
|
|
1
|
+
import { builtinFunctions, keywords, typeKeywords } from './yql.keywords';
|
2
|
+
export const conf = {
|
3
|
+
comments: {
|
4
|
+
lineComment: '--',
|
5
|
+
blockComment: ['/*', '*/'],
|
6
|
+
},
|
7
|
+
brackets: [
|
8
|
+
['{', '}'],
|
9
|
+
['[', ']'],
|
10
|
+
['(', ')'],
|
11
|
+
],
|
12
|
+
autoClosingPairs: [
|
13
|
+
{ open: '{', close: '}' },
|
14
|
+
{ open: '[', close: ']' },
|
15
|
+
{ open: '(', close: ')' },
|
16
|
+
{ open: '"', close: '"' },
|
17
|
+
{ open: "'", close: "'" },
|
18
|
+
{ open: '`', close: '`' },
|
19
|
+
],
|
20
|
+
surroundingPairs: [
|
21
|
+
{ open: '{', close: '}' },
|
22
|
+
{ open: '[', close: ']' },
|
23
|
+
{ open: '(', close: ')' },
|
24
|
+
{ open: '"', close: '"' },
|
25
|
+
{ open: "'", close: "'" },
|
26
|
+
{ open: '`', close: '`' },
|
27
|
+
],
|
28
|
+
wordPattern: /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",./?\s]+)/g,
|
29
|
+
};
|
30
|
+
export function getLanguage({ ansi = false, } = {}) {
|
31
|
+
return {
|
32
|
+
defaultToken: 'text',
|
33
|
+
ignoreCase: true,
|
34
|
+
brackets: [
|
35
|
+
{ open: '[', close: ']', token: 'delimiter.square' },
|
36
|
+
{ open: '(', close: ')', token: 'delimiter.parenthesis' },
|
37
|
+
{ open: '{', close: '}', token: 'delimiter.curly' },
|
38
|
+
],
|
39
|
+
keywords,
|
40
|
+
typeKeywords,
|
41
|
+
constants: ['true', 'false'],
|
42
|
+
builtinFunctions,
|
43
|
+
operators: [
|
44
|
+
'+',
|
45
|
+
'-',
|
46
|
+
'/',
|
47
|
+
'//',
|
48
|
+
'%',
|
49
|
+
'<@>',
|
50
|
+
'@>',
|
51
|
+
'<@',
|
52
|
+
'&',
|
53
|
+
'^',
|
54
|
+
'~',
|
55
|
+
'<',
|
56
|
+
'>',
|
57
|
+
'<=',
|
58
|
+
'>=',
|
59
|
+
'=>',
|
60
|
+
'==',
|
61
|
+
'!=',
|
62
|
+
'<>',
|
63
|
+
'=',
|
64
|
+
],
|
65
|
+
symbols: /[=><!~?:&|+\-*/^%]+/,
|
66
|
+
escapes: /\\(?:[abfnrtv\\"'`]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
|
67
|
+
variables: /[a-zA-Z_]\w*/,
|
68
|
+
tokenizer: {
|
69
|
+
root: [
|
70
|
+
{ include: '@whitespace' },
|
71
|
+
{ include: '@comments' },
|
72
|
+
{ include: '@numbers' },
|
73
|
+
{ include: '@tablePath' },
|
74
|
+
{ include: '@strings' },
|
75
|
+
// support function
|
76
|
+
[/(@variables)::(@variables)/, 'support.function'],
|
77
|
+
[/[;,.]/, 'delimiter'],
|
78
|
+
[/[(){}[\]]/, '@brackets'],
|
79
|
+
// identifiers and keywords
|
80
|
+
[
|
81
|
+
/@?[a-zA-Z_$]\w*/,
|
82
|
+
{
|
83
|
+
cases: {
|
84
|
+
'@keywords': 'keyword',
|
85
|
+
'@typeKeywords': 'keyword.type',
|
86
|
+
'@constants': 'constant.yql',
|
87
|
+
'@builtinFunctions': 'constant.other.color',
|
88
|
+
'[$@][a-zA-Z_]\\w*': 'variable',
|
89
|
+
'@default': 'identifier',
|
90
|
+
},
|
91
|
+
},
|
92
|
+
],
|
93
|
+
[
|
94
|
+
/@symbols/,
|
95
|
+
{
|
96
|
+
cases: {
|
97
|
+
'@operators': 'operator.sql',
|
98
|
+
'@default': '',
|
99
|
+
},
|
100
|
+
},
|
101
|
+
],
|
102
|
+
],
|
103
|
+
whitespace: [[/\s+/, 'white']],
|
104
|
+
comments: [
|
105
|
+
[/--.*/, 'comment'],
|
106
|
+
[/\/\*/, { token: 'comment.quote', next: ansi ? '@commentAnsi' : '@comment' }],
|
107
|
+
],
|
108
|
+
comment: [
|
109
|
+
[/[^*/]+/, 'comment'],
|
110
|
+
[/\*\//, { token: 'comment.quote', next: '@pop' }],
|
111
|
+
[/./, 'comment'],
|
112
|
+
],
|
113
|
+
commentAnsi: [
|
114
|
+
[/\/\*/, { token: 'comment.quote', next: '@comment' }],
|
115
|
+
[/[^*/]+/, 'comment'],
|
116
|
+
[/\*\//, { token: 'comment.quote', next: '@pop' }],
|
117
|
+
[/./, 'comment'],
|
118
|
+
],
|
119
|
+
numbers: [
|
120
|
+
[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?f?\b/, 'number.float'],
|
121
|
+
[/[+-]?(?:\d+|0b[01]+|0o[0-8]+|0x[\da-f]+)(?:u?[lst]?)?\b/, 'number'],
|
122
|
+
],
|
123
|
+
strings: [
|
124
|
+
[/'/, { token: 'string', next: ansi ? '@stringAnsiSingle' : '@stringSingle' }],
|
125
|
+
[/"/, { token: 'string', next: ansi ? '@stringAnsiDouble' : '@stringDouble' }],
|
126
|
+
[/[@]{2}/, { token: 'string', next: '@multilineString' }],
|
127
|
+
],
|
128
|
+
stringSingle: [
|
129
|
+
[/[^\\']+/, 'string'],
|
130
|
+
[/@escapes/, 'string.escape'],
|
131
|
+
[/\\./, 'string.escape.invalid'],
|
132
|
+
[/'[uyj]?/, { token: 'string', next: '@pop' }],
|
133
|
+
],
|
134
|
+
stringAnsiSingle: [
|
135
|
+
[/[^']+/, 'string'],
|
136
|
+
[/''/, 'string'],
|
137
|
+
[/'[uyj]?/, { token: 'string', next: '@pop' }],
|
138
|
+
],
|
139
|
+
stringDouble: [
|
140
|
+
[/[^\\"]+/, 'string'],
|
141
|
+
[/@escapes/, 'string.escape'],
|
142
|
+
[/\\./, 'string.escape.invalid'],
|
143
|
+
[/"[uyj]?/, { token: 'string', next: '@pop' }],
|
144
|
+
],
|
145
|
+
stringAnsiDouble: [
|
146
|
+
[/[^"]+/, 'string'],
|
147
|
+
[/""/, 'string'],
|
148
|
+
[/"[uyj]?/, { token: 'string', next: '@pop' }],
|
149
|
+
],
|
150
|
+
multilineString: [
|
151
|
+
[
|
152
|
+
/#py/,
|
153
|
+
{ token: 'string.python', nextEmbedded: 'python', next: '@embedded', goBack: 3 },
|
154
|
+
],
|
155
|
+
[
|
156
|
+
/\/\/js/,
|
157
|
+
{ token: 'string.js', nextEmbedded: 'javascript', next: '@embedded', goBack: 4 },
|
158
|
+
],
|
159
|
+
[/[^@]+/, 'string'],
|
160
|
+
[/[@]{4}/, 'string'],
|
161
|
+
[/[@]{2}[uyj]?/, { token: 'string', next: '@pop' }],
|
162
|
+
[/./, 'string'],
|
163
|
+
],
|
164
|
+
embedded: [
|
165
|
+
[
|
166
|
+
/([^@]|^)([@]{4})*[@]{2}([@]([^@]|$)|[^@]|$)/,
|
167
|
+
{ token: '@rematch', next: '@pop', nextEmbedded: '@pop' },
|
168
|
+
],
|
169
|
+
],
|
170
|
+
tablePath: [[/((`)?[\w/]+\2\s*\.\s*)?`/, { token: 'string.tablepath', next: '@table' }]],
|
171
|
+
table: [
|
172
|
+
[/[^\\`]+/, 'string.tablepath'],
|
173
|
+
[/``/, 'string.tablepath'],
|
174
|
+
[/@escapes/, 'string.escape.tablepath'],
|
175
|
+
[/\\./, 'string.escape.invalid.tablepath'],
|
176
|
+
[/`/, { token: 'string.tablepath', next: '@pop' }],
|
177
|
+
],
|
178
|
+
},
|
179
|
+
};
|
180
|
+
}
|
@@ -0,0 +1,3 @@
|
|
1
|
+
export const keywords = '$row|$rows|action|all|and|any|as|asc|assume|begin|bernoulli|between|by|case|columns|commit|compact|create|cross|cube|declare|define|delete|desc|dict|discard|distinct|do|drop|else|empty_action|end|erase|evaluate|exclusion|exists|export|flatten|for|from|full|group|grouping|having|if|ignore|ilike|import|in|inner|insert|into|is|join|left|like|limit|list|match|not|null|nulls|offset|on|only|optional|or|order|over|partition|pragma|presort|process|reduce|regexp|repeatable|replace|respect|result|return|right|rlike|rollup|sample|schema|select|semi|set|sets|stream|subquery|table|tablesample|then|truncate|union|update|upsert|use|using|values|view|when|where|window|with|without|xor'.split('|');
|
2
|
+
export const typeKeywords = 'bool|date|datetime|decimal|double|float|int16|int32|int64|int8|interval|json|string|timestamp|tzdate|tzdatetime|tztimestamp|uint16|uint32|uint64|uint8|utf8|uuid|yson'.split('|');
|
3
|
+
export const builtinFunctions = 'abs|aggregate_by|aggregate_list|aggregate_list_distinct|agg_list|agg_list_distinct|as_table|avg|avg_if|adaptivedistancehistogram|adaptivewardhistogram|adaptiveweighthistogram|addmember|addtimezone|aggregateflatten|aggregatetransforminput|aggregatetransformoutput|aggregationfactory|asatom|asdict|asdictstrict|asenum|aslist|asliststrict|asset|assetstrict|asstruct|astagged|astuple|asvariant|atomcode|bitcast|bit_and|bit_or|bit_xor|bool_and|bool_or|bool_xor|bottom|bottom_by|blockwardhistogram|blockweighthistogram|cast|coalesce|concat|concat_strict|correlation|count|count_if|covariance|covariance_population|covariance_sample|callableargument|callableargumenttype|callableresulttype|callabletype|callabletypecomponents|callabletypehandle|choosemembers|combinemembers|countdistinctestimate|currentauthenticateduser|currentoperationid|currentoperationsharedid|currenttzdate|currenttzdatetime|currenttztimestamp|currentutcdate|currentutcdatetime|currentutctimestamp|dense_rank|datatype|datatypecomponents|datatypehandle|dictaggregate|dictcontains|dictcreate|dicthasitems|dictitems|dictkeytype|dictkeys|dictlength|dictlookup|dictpayloadtype|dictpayloads|dicttype|dicttypecomponents|dicttypehandle|each|each_strict|emptydicttype|emptydicttypehandle|emptylisttype|emptylisttypehandle|endswith|ensure|ensureconvertibleto|ensuretype|enum|evaluateatom|evaluatecode|evaluateexpr|evaluatetype|expandstruct|filter|filter_strict|find|first_value|folder|filecontent|filepath|flattenmembers|forceremovemember|forceremovemembers|forcerenamemembers|forcespreadmembers|formatcode|formattype|frombytes|funccode|greatest|grouping|gathermembers|generictype|histogram|hll|hyperloglog|if|if_strict|instanceof|json_exists|json_query|json_value|jointablerow|just|lag|last_value|lead|least|len|length|like|likely|like_strict|lambdaargumentscount|lambdacode|linearhistogram|listaggregate|listall|listany|listavg|listcode|listcollect|listconcat|listcreate|listdistinct|listenumerate|listextend|listextendstrict|listextract|listfilter|listflatmap|listflatten|listfromrange|listhas|listhasitems|listhead|listindexof|listitemtype|listlast|listlength|listmap|listmax|listmin|listnotnull|listreplicate|listreverse|listskip|listskipwhile|listskipwhileinclusive|listsort|listsortasc|listsortdesc|listsum|listtake|listtakewhile|listtakewhileinclusive|listtype|listtypehandle|listunionall|listuniq|listzip|listzipall|loghistogram|logarithmichistogram|max|max_by|max_of|median|min|min_by|min_of|mode|multi_aggregate_by|nanvl|nvl|nothing|nulltype|nulltypehandle|optionalitemtype|optionaltype|optionaltypehandle|percentile|parsefile|parsetype|parsetypehandle|pickle|quotecode|range|range_strict|rank|regexp|regexp_strict|rfind|row_number|random|randomnumber|randomuuid|removemember|removemembers|removetimezone|renamemembers|replacemember|reprcode|resourcetype|resourcetypehandle|resourcetypetag|some|stddev|stddev_population|stddev_sample|substring|sum|sum_if|sessionstart|sessionwindow|setcreate|setdifference|setincludes|setintersection|setisdisjoint|setsymmetricdifference|setunion|spreadmembers|stablepickle|startswith|staticmap|streamitemtype|streamtype|streamtypehandle|structmembertype|structmembers|structtypecomponents|structtypehandle|subqueryextend|subqueryextendfor|subquerymerge|subquerymergefor|subqueryunionall|subqueryunionallfor|subqueryunionmerge|subqueryunionmergefor|top|topfreq|top_by|tablename|tablepath|tablerecordindex|tablerow|taggedtype|taggedtypecomponents|taggedtypehandle|tobytes|todict|tomultidict|toset|tosorteddict|tosortedmultidict|trymember|tupleelementtype|tupletype|tupletypecomponents|tupletypehandle|typehandle|typekind|typeof|udaf|unittype|unpickle|untag|unwrap|variance|variance_population|variance_sample|variant|varianttype|varianttypehandle|variantunderlyingtype|voidtype|voidtypehandle|way|worldcode'.split('|');
|
@@ -1,18 +1,24 @@
|
|
1
1
|
import { generateAggregateFunctionsSuggestion, generateColumnAliasesSuggestion, generateColumnsSuggestion, generateEntitiesSuggestion, generateKeywordsSuggestion, generatePragmasSuggestion, generateSimpleFunctionsSuggestion, generateSimpleTypesSuggestion, generateTableFunctionsSuggestion, generateUdfSuggestion, generateWindowFunctionsSuggestion, } from './generateSuggestions';
|
2
2
|
export function createProvideSuggestionsFunction(database) {
|
3
3
|
return async (model, monacoCursorPosition, _context, _token) => {
|
4
|
-
const cursorPosition = {
|
5
|
-
line: monacoCursorPosition.lineNumber,
|
6
|
-
column: monacoCursorPosition.column,
|
7
|
-
};
|
8
4
|
const rangeToInsertSuggestion = getRangeToInsertSuggestion(model, monacoCursorPosition);
|
9
|
-
const suggestions = await getSuggestions(model,
|
5
|
+
const suggestions = await getSuggestions(model, monacoCursorPosition, rangeToInsertSuggestion, database);
|
10
6
|
return { suggestions };
|
11
7
|
};
|
12
8
|
}
|
9
|
+
function getEntityNameAtCursor(model, cursorPosition) {
|
10
|
+
var _a, _b, _c, _d;
|
11
|
+
const prevWord = model.findPreviousMatch('\\s(`?[^\\s]*)', cursorPosition, true, false, null, true);
|
12
|
+
const nextWord = model.findNextMatch('([^\\s]*)`?', cursorPosition, true, false, null, true);
|
13
|
+
return `${(_b = (_a = prevWord === null || prevWord === void 0 ? void 0 : prevWord.matches) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''}${(_d = (_c = nextWord === null || nextWord === void 0 ? void 0 : nextWord.matches) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''}`;
|
14
|
+
}
|
13
15
|
async function getSuggestions(model, cursorPosition, rangeToInsertSuggestion, database) {
|
14
16
|
const { parseYqlQuery } = await import('@gravity-ui/websql-autocomplete');
|
15
|
-
const
|
17
|
+
const cursorForParsing = {
|
18
|
+
line: cursorPosition.lineNumber,
|
19
|
+
column: cursorPosition.column,
|
20
|
+
};
|
21
|
+
const parseResult = parseYqlQuery(model.getValue(), cursorForParsing);
|
16
22
|
let entitiesSuggestions = [];
|
17
23
|
let functionsSuggestions = [];
|
18
24
|
let aggregateFunctionsSuggestions = [];
|
@@ -22,7 +28,8 @@ async function getSuggestions(model, cursorPosition, rangeToInsertSuggestion, da
|
|
22
28
|
let simpleTypesSuggestions = [];
|
23
29
|
let pragmasSuggestions = [];
|
24
30
|
if (parseResult.suggestEntity) {
|
25
|
-
|
31
|
+
const entityNamePrefix = getEntityNameAtCursor(model, cursorPosition);
|
32
|
+
entitiesSuggestions = await generateEntitiesSuggestion(rangeToInsertSuggestion, parseResult.suggestEntity, database, entityNamePrefix);
|
26
33
|
}
|
27
34
|
if (parseResult.suggestFunctions) {
|
28
35
|
functionsSuggestions = await generateSimpleFunctionsSuggestion(rangeToInsertSuggestion);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ydb-embedded-ui",
|
3
|
-
"version": "6.0
|
3
|
+
"version": "6.1.0",
|
4
4
|
"files": [
|
5
5
|
"dist"
|
6
6
|
],
|
@@ -21,7 +21,7 @@
|
|
21
21
|
"@gravity-ui/paranoid": "^1.4.1",
|
22
22
|
"@gravity-ui/react-data-table": "^2.0.1",
|
23
23
|
"@gravity-ui/uikit": "^6.10.2",
|
24
|
-
"@gravity-ui/websql-autocomplete": "^8.0
|
24
|
+
"@gravity-ui/websql-autocomplete": "^8.1.0",
|
25
25
|
"@reduxjs/toolkit": "^2.2.3",
|
26
26
|
"axios": "^1.6.8",
|
27
27
|
"colord": "^2.9.3",
|
@@ -70,7 +70,7 @@
|
|
70
70
|
"prepublishOnly": "npm run package",
|
71
71
|
"typecheck": "tsc --noEmit",
|
72
72
|
"prepare": "husky",
|
73
|
-
"test:e2e:install": "npx playwright install --with-deps
|
73
|
+
"test:e2e:install": "npx playwright install --with-deps",
|
74
74
|
"test:e2e": "npx playwright test --config=playwright.config.ts"
|
75
75
|
},
|
76
76
|
"lint-staged": {
|
File without changes
|
File without changes
|