ydb-embedded-ui 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/dist/components/CriticalActionDialog/CriticalActionDialog.scss +0 -2
  2. package/dist/containers/PDiskPage/PDiskPage.js +6 -1
  3. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +2 -1
  4. package/dist/containers/Tenant/Query/QueryEditor/helpers.js +4 -3
  5. package/dist/containers/Tenant/Tenant.js +1 -1
  6. package/dist/containers/UserSettings/i18n/en.json +2 -0
  7. package/dist/containers/UserSettings/i18n/index.d.ts +1 -1
  8. package/dist/containers/UserSettings/settings.d.ts +1 -0
  9. package/dist/containers/UserSettings/settings.js +7 -2
  10. package/dist/services/api.d.ts +9 -1
  11. package/dist/services/api.js +5 -0
  12. package/dist/services/settings.js +2 -1
  13. package/dist/types/api/autocomplete.d.ts +21 -0
  14. package/dist/types/api/autocomplete.js +1 -0
  15. package/dist/types/api/restartPDisk.d.ts +4 -0
  16. package/dist/types/api/restartPDisk.js +1 -0
  17. package/dist/utils/constants.d.ts +1 -0
  18. package/dist/utils/constants.js +1 -0
  19. package/dist/utils/monaco/index.js +2 -0
  20. package/dist/utils/monaco/{yqlSuggestions → yql}/constants.d.ts +1 -0
  21. package/dist/utils/monaco/{yqlSuggestions → yql}/constants.js +1 -0
  22. package/dist/utils/monaco/{yqlSuggestions → yql}/generateSuggestions.d.ts +3 -3
  23. package/dist/utils/monaco/{yqlSuggestions → yql}/generateSuggestions.js +124 -64
  24. package/dist/utils/monaco/yql/registerLanguage.d.ts +1 -0
  25. package/dist/utils/monaco/yql/registerLanguage.js +8 -0
  26. package/dist/utils/monaco/{yqlSuggestions/registerCompletionItemProvider.js → yql/yql.completionItemProvider.js} +3 -2
  27. package/dist/utils/monaco/yql/yql.d.ts +7 -0
  28. package/dist/utils/monaco/yql/yql.js +180 -0
  29. package/dist/utils/monaco/yql/yql.keywords.d.ts +3 -0
  30. package/dist/utils/monaco/yql/yql.keywords.js +3 -0
  31. package/dist/utils/monaco/{yqlSuggestions → yql}/yqlSuggestions.js +14 -7
  32. package/package.json +6 -5
  33. /package/dist/utils/monaco/{yqlSuggestions/registerCompletionItemProvider.d.ts → yql/yql.completionItemProvider.d.ts} +0 -0
  34. /package/dist/utils/monaco/{yqlSuggestions → yql}/yqlSuggestions.d.ts +0 -0
@@ -15,7 +15,5 @@
15
15
  &__body {
16
16
  display: flex;
17
17
  align-items: center;
18
-
19
- padding: 16px 16px 0;
20
18
  }
21
19
  }
@@ -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: "sql", 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
+ }), 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/yqlSuggestions/registerCompletionItemProvider');
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',
@@ -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<any>;
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>;
@@ -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,4 @@
1
+ export interface RestartPDiskResponse {
2
+ result?: boolean;
3
+ error?: string;
4
+ }
@@ -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";
@@ -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,4 +1,6 @@
1
1
  import { registerSExpressionLanguage } from './s-expression/registerLanguage';
2
+ import { registerYqlLanguage } from './yql/registerLanguage';
2
3
  export function registerLanguages() {
3
4
  registerSExpressionLanguage();
5
+ registerYqlLanguage();
4
6
  }
@@ -1,3 +1,4 @@
1
+ export declare const LANGUAGE_YQL_ID = "yql";
1
2
  export declare const SimpleTypes: string[];
2
3
  export declare const SimpleFunctions: string[];
3
4
  export declare const AggregateFunctions: string[];
@@ -1,3 +1,4 @@
1
+ export const LANGUAGE_YQL_ID = 'yql';
1
2
  export const SimpleTypes = [
2
3
  'String',
3
4
  'Bool',
@@ -1,5 +1,5 @@
1
- import type { ColumnAliasSuggestion, KeywordSuggestion, YqlAutocompleteResult } from '@gravity-ui/websql-autocomplete';
2
- import type * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
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(_rangeToInsertSuggestion: monaco.IRange): Promise<monaco.languages.CompletionItem[]>;
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 normalizedValue = value;
63
+ let sliceStart = 0;
64
+ let sliceEnd = value.length;
42
65
  if (value.startsWith('`')) {
43
- normalizedValue = value.slice(1, -1);
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 normalizedValue;
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
- for (const entity of (_a = suggestColumns.tables) !== null && _a !== void 0 ? _a : []) {
132
+ const normalizedTableNames = (_b = (_a = suggestColumns.tables) === null || _a === void 0 ? void 0 : _a.map((entity) => {
137
133
  let normalizedEntityName = removeBackticks(entity.name);
138
- // if it's relative entity path
139
- if (!normalizedEntityName.startsWith('/')) {
140
- normalizedEntityName = `${database}/${normalizedEntityName}`;
134
+ if (!normalizedEntityName.endsWith('/')) {
135
+ normalizedEntityName = `${normalizedEntityName}/`;
141
136
  }
142
- const fields = await getColumns(normalizedEntityName);
143
- fields.forEach((columnName) => {
144
- const normalizedName = wrapStringToBackticks(columnName);
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 (entity.alias) {
147
- columnNameSuggestion = `${entity.alias}.${normalizedName}`;
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(_rangeToInsertSuggestion) {
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('sql', {
12
- triggerCharacters: [' ', '\n', '', ',', '.', '`', '('],
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 declare const keywords: string[];
2
+ export declare const typeKeywords: string[];
3
+ export declare const builtinFunctions: string[];
@@ -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, cursorPosition, rangeToInsertSuggestion, database);
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 parseResult = parseYqlQuery(model.getValue(), cursorPosition);
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
- entitiesSuggestions = await generateEntitiesSuggestion(rangeToInsertSuggestion);
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.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.2",
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",
@@ -29,7 +29,7 @@
29
29
  "crc-32": "^1.2.2",
30
30
  "history": "^4.10.1",
31
31
  "lodash": "^4.17.21",
32
- "monaco-editor": "^0.44.0",
32
+ "monaco-editor": "^0.48.0",
33
33
  "numeral": "^2.0.6",
34
34
  "path-to-regexp": "^3.0.0",
35
35
  "qs": "^6.12.0",
@@ -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 chromium",
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": {
@@ -167,6 +167,7 @@
167
167
  "react": "^18.2.0",
168
168
  "react-dom": "^18.2.0",
169
169
  "redux": "^5.0.1",
170
- "typescript": "^5.4.3"
170
+ "typescript": "^5.4.3",
171
+ "monaco-editor": "^0.48.0"
171
172
  }
172
173
  }