Dev/sda/adds prettier updates eslint (#2311)
chore: Updates linter - Eslint has been updated - Prettier has been added - Code has been updated using new rules - Fixes rule suggestions
This commit is contained in:
Родитель
519ed5e697
Коммит
4ca6fd6de0
|
@ -2,3 +2,5 @@ gulpfile.ts
|
|||
.eslintrc.js
|
||||
**/*.d.ts
|
||||
test/
|
||||
webpack.config.js
|
||||
webpack.config.*.js
|
||||
|
|
47
.eslintrc.js
47
.eslintrc.js
|
@ -1,8 +1,43 @@
|
|||
module.exports = {
|
||||
"extends": "@microsoft/eslint-config-azuretools",
|
||||
"rules": {
|
||||
"import/no-internal-modules": [ "error", {
|
||||
"allow": [ "antlr4ts/**" ]
|
||||
} ]
|
||||
}
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'import'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-restricted-types': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-inferrable-types': 'off',
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
'@typescript-eslint/require-await': 'warn',
|
||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||
'@typescript-eslint/unbound-method': 'warn',
|
||||
eqeqeq: ['error', 'always'],
|
||||
'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
|
||||
'import/no-internal-modules': [
|
||||
'error',
|
||||
{
|
||||
allow: ['antlr4ts/**', 'yaml/types'],
|
||||
},
|
||||
],
|
||||
'no-case-declarations': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
'no-inner-declarations': 'error',
|
||||
'no-restricted-imports': ['error', { patterns: ['**/*/extension.bundle'] }],
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'no-useless-escape': 'error',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"arrowParens": "always",
|
||||
"plugins": ["prettier-plugin-organize-imports"]
|
||||
}
|
10
gulpfile.ts
10
gulpfile.ts
|
@ -13,16 +13,18 @@ declare let exports: { [key: string]: unknown };
|
|||
async function prepareForWebpack(): Promise<void> {
|
||||
const mainJsPath: string = path.join(__dirname, 'main.js');
|
||||
let contents: string = (await fse.readFile(mainJsPath)).toString();
|
||||
contents = contents
|
||||
.replace('out/src/extension', 'dist/extension.bundle')
|
||||
.replace(', true /* ignoreBundle */', '');
|
||||
contents = contents.replace('out/src/extension', 'dist/extension.bundle').replace(', true /* ignoreBundle */', '');
|
||||
await fse.writeFile(mainJsPath, contents);
|
||||
}
|
||||
|
||||
async function cleanReadme(): Promise<void> {
|
||||
const readmePath: string = path.join(__dirname, 'README.md');
|
||||
let data: string = (await fse.readFile(readmePath)).toString();
|
||||
data = data.replace(/<!-- region exclude-from-marketplace -->.*?<!-- endregion exclude-from-marketplace -->/gis, '');
|
||||
data = data.replace(
|
||||
// @ts-ignore
|
||||
/<!-- region exclude-from-marketplace -->.*?<!-- endregion exclude-from-marketplace -->/gis,
|
||||
'',
|
||||
);
|
||||
await fse.writeFile(readmePath, data);
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
16
package.json
16
package.json
|
@ -1086,8 +1086,8 @@
|
|||
"compile": "tsc -watch",
|
||||
"package": "vsce package --githubBranch main",
|
||||
"package-local": "vsce package",
|
||||
"lint": "eslint --ext .ts .",
|
||||
"lint-fix": "eslint --ext .ts . --fix",
|
||||
"lint": "eslint --quiet --ext .ts --ext .tsx .",
|
||||
"lint-fix": "eslint --ext .ts --ext .tsx . --fix",
|
||||
"pretest": "npm run webpack-prod",
|
||||
"test": "node ./out/test/runTest.js",
|
||||
"unittest": "mocha ./out/test/unit/**/*.js",
|
||||
|
@ -1100,7 +1100,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@azure/arm-resources": "^4.0.0",
|
||||
"@microsoft/eslint-config-azuretools": "^0.1.0",
|
||||
"@microsoft/vscode-azext-dev": "^2.0.4",
|
||||
"@types/copy-webpack-plugin": "^6.4.0",
|
||||
"@types/documentdb": "^1.10.2",
|
||||
|
@ -1110,20 +1109,23 @@
|
|||
"@types/node": "^14.0.0",
|
||||
"@types/pg": "^8.10.2",
|
||||
"@types/vscode": "1.82.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.5.0",
|
||||
"@typescript-eslint/parser": "^8.5.0",
|
||||
"@vscode/test-electron": "^2.3.8",
|
||||
"antlr4ts-cli": "^0.4.0-alpha.4",
|
||||
"copy-webpack-plugin": "^6.4.0",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.0",
|
||||
"husky": "^7.0.2",
|
||||
"mocha": "^10.2.0",
|
||||
"mocha-junit-reporter": "^1.18.0",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-organize-imports": "^4.0.0",
|
||||
"ts-node": "^7.0.1",
|
||||
"typescript": "^4.4.3",
|
||||
"typescript": "^5.5.4",
|
||||
"vsce": "^1.87.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack-cli": "^4.6.0",
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import { IAzureQuickPickItem } from '@microsoft/vscode-azext-utils';
|
||||
import { type DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import { type IAzureQuickPickItem } from '@microsoft/vscode-azext-utils';
|
||||
import { nonNullProp } from './utils/nonNull';
|
||||
|
||||
export enum API {
|
||||
|
@ -13,12 +13,12 @@ export enum API {
|
|||
Table = 'Table',
|
||||
Core = 'Core',
|
||||
PostgresSingle = 'PostgresSingle',
|
||||
PostgresFlexible = 'PostgresFlexible'
|
||||
PostgresFlexible = 'PostgresFlexible',
|
||||
}
|
||||
|
||||
export enum DBAccountKind {
|
||||
MongoDB = 'MongoDB',
|
||||
GlobalDocumentDB = 'GlobalDocumentDB'
|
||||
GlobalDocumentDB = 'GlobalDocumentDB',
|
||||
}
|
||||
|
||||
export type CapabilityName = 'EnableGremlin' | 'EnableTable';
|
||||
|
@ -32,26 +32,26 @@ export function getExperienceFromApi(api: API): Experience {
|
|||
}
|
||||
|
||||
export function getExperienceLabel(databaseAccount: DatabaseAccountGetResults): string {
|
||||
|
||||
const experience: Experience | undefined = tryGetExperience(databaseAccount);
|
||||
if (experience) {
|
||||
return experience.shortName;
|
||||
}
|
||||
// Must be some new kind of resource that we aren't aware of. Try to get a decent label
|
||||
const defaultExperience: string = <API>(databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience);
|
||||
const defaultExperience: string = <API>(
|
||||
(databaseAccount && databaseAccount.tags && databaseAccount.tags.defaultExperience)
|
||||
);
|
||||
const firstCapability = databaseAccount.capabilities && databaseAccount.capabilities[0];
|
||||
const firstCapabilityName = firstCapability?.name?.replace(/^Enable/, '');
|
||||
return defaultExperience || firstCapabilityName || nonNullProp(databaseAccount, 'kind');
|
||||
|
||||
}
|
||||
|
||||
export function tryGetExperience(resource: DatabaseAccountGetResults): Experience | undefined {
|
||||
// defaultExperience in the resource doesn't really mean anything, we can't depend on its value for determining resource type
|
||||
if (resource.kind === DBAccountKind.MongoDB) {
|
||||
return MongoExperience;
|
||||
} else if (resource.capabilities?.find(cap => cap.name === 'EnableGremlin')) {
|
||||
} else if (resource.capabilities?.find((cap) => cap.name === 'EnableGremlin')) {
|
||||
return GremlinExperience;
|
||||
} else if (resource.capabilities?.find(cap => cap.name === 'EnableTable')) {
|
||||
} else if (resource.capabilities?.find((cap) => cap.name === 'EnableTable')) {
|
||||
return TableExperience;
|
||||
} else if (resource.capabilities?.length === 0) {
|
||||
return CoreExperience;
|
||||
|
@ -80,17 +80,17 @@ export interface Experience {
|
|||
|
||||
export function getExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem<Experience>[] {
|
||||
if (attached) {
|
||||
return experiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api));
|
||||
return experiencesArray.map((exp) => getExperienceQuickPickForAttached(exp.api));
|
||||
} else {
|
||||
return experiencesArray.map(exp => getExperienceQuickPick(exp.api));
|
||||
return experiencesArray.map((exp) => getExperienceQuickPick(exp.api));
|
||||
}
|
||||
}
|
||||
|
||||
export function getCosmosExperienceQuickPicks(attached?: boolean): IAzureQuickPickItem<Experience>[] {
|
||||
if (attached) {
|
||||
return cosmosExperiencesArray.map(exp => getExperienceQuickPickForAttached(exp.api));
|
||||
return cosmosExperiencesArray.map((exp) => getExperienceQuickPickForAttached(exp.api));
|
||||
} else {
|
||||
return cosmosExperiencesArray.map(exp => getExperienceQuickPick(exp.api));
|
||||
return cosmosExperiencesArray.map((exp) => getExperienceQuickPick(exp.api));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,13 +106,55 @@ export function getExperienceQuickPickForAttached(api: API): IAzureQuickPickItem
|
|||
|
||||
// Mongo is distinguished by having kind="MongoDB". All others have kind="GlobalDocumentDB"
|
||||
// Table and Gremlin are distinguished from SQL by their capabilities
|
||||
export const CoreExperience: Experience = { api: API.Core, longName: "Core", description: "(SQL)", shortName: "SQL", kind: DBAccountKind.GlobalDocumentDB, tag: 'Core (SQL)' } as const;
|
||||
export const MongoExperience: Experience = { api: API.MongoDB, longName: "Azure Cosmos DB for MongoDB API", shortName: "MongoDB", kind: DBAccountKind.MongoDB, tag: "Azure Cosmos DB for MongoDB API" } as const;
|
||||
export const TableExperience: Experience = { api: API.Table, longName: "Azure Table", shortName: "Table", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableTable', tag: 'Azure Table' } as const;
|
||||
export const GremlinExperience: Experience = { api: API.Graph, longName: "Gremlin", description: "(graph)", shortName: "Gremlin", kind: DBAccountKind.GlobalDocumentDB, capability: 'EnableGremlin', tag: 'Gremlin (graph)' } as const;
|
||||
const PostgresSingleExperience: Experience = { api: API.PostgresSingle, longName: "PostgreSQL Single Server", shortName: "PostgreSQLSingle" };
|
||||
const PostgresFlexibleExperience: Experience = { api: API.PostgresFlexible, longName: "PostgreSQL Flexible Server", shortName: "PostgreSQLFlexible" };
|
||||
export const CoreExperience: Experience = {
|
||||
api: API.Core,
|
||||
longName: 'Core',
|
||||
description: '(SQL)',
|
||||
shortName: 'SQL',
|
||||
kind: DBAccountKind.GlobalDocumentDB,
|
||||
tag: 'Core (SQL)',
|
||||
} as const;
|
||||
export const MongoExperience: Experience = {
|
||||
api: API.MongoDB,
|
||||
longName: 'Azure Cosmos DB for MongoDB API',
|
||||
shortName: 'MongoDB',
|
||||
kind: DBAccountKind.MongoDB,
|
||||
tag: 'Azure Cosmos DB for MongoDB API',
|
||||
} as const;
|
||||
export const TableExperience: Experience = {
|
||||
api: API.Table,
|
||||
longName: 'Azure Table',
|
||||
shortName: 'Table',
|
||||
kind: DBAccountKind.GlobalDocumentDB,
|
||||
capability: 'EnableTable',
|
||||
tag: 'Azure Table',
|
||||
} as const;
|
||||
export const GremlinExperience: Experience = {
|
||||
api: API.Graph,
|
||||
longName: 'Gremlin',
|
||||
description: '(graph)',
|
||||
shortName: 'Gremlin',
|
||||
kind: DBAccountKind.GlobalDocumentDB,
|
||||
capability: 'EnableGremlin',
|
||||
tag: 'Gremlin (graph)',
|
||||
} as const;
|
||||
const PostgresSingleExperience: Experience = {
|
||||
api: API.PostgresSingle,
|
||||
longName: 'PostgreSQL Single Server',
|
||||
shortName: 'PostgreSQLSingle',
|
||||
};
|
||||
const PostgresFlexibleExperience: Experience = {
|
||||
api: API.PostgresFlexible,
|
||||
longName: 'PostgreSQL Flexible Server',
|
||||
shortName: 'PostgreSQLFlexible',
|
||||
};
|
||||
|
||||
const cosmosExperiencesArray: Experience[] = [CoreExperience, MongoExperience, TableExperience, GremlinExperience];
|
||||
const experiencesArray: Experience[] = [...cosmosExperiencesArray, PostgresSingleExperience, PostgresFlexibleExperience];
|
||||
const experiencesMap = new Map<API, Experience>(experiencesArray.map((info: Experience): [API, Experience] => [info.api, info]));
|
||||
const experiencesArray: Experience[] = [
|
||||
...cosmosExperiencesArray,
|
||||
PostgresSingleExperience,
|
||||
PostgresFlexibleExperience,
|
||||
];
|
||||
const experiencesMap = new Map<API, Experience>(
|
||||
experiencesArray.map((info: Experience): [API, Experience] => [info.api, info]),
|
||||
);
|
||||
|
|
|
@ -3,13 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeFileSystem, AzExtTreeItem, DialogResponses, IActionContext, UserCancelledError } from '@microsoft/vscode-azext-utils';
|
||||
import { FileStat, FileType, MessageItem, Uri, workspace } from "vscode";
|
||||
import { FileChangeType } from "vscode-languageclient";
|
||||
import { ext } from "./extensionVariables";
|
||||
import { localize } from "./utils/localize";
|
||||
import { getWorkspaceSetting, updateGlobalSetting } from "./utils/settingUtils";
|
||||
import { getNodeEditorLabel } from "./utils/vscodeUtils";
|
||||
import {
|
||||
AzExtTreeFileSystem,
|
||||
DialogResponses,
|
||||
UserCancelledError,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { FileType, workspace, type FileStat, type MessageItem, type Uri } from 'vscode';
|
||||
import { FileChangeType } from 'vscode-languageclient';
|
||||
import { ext } from './extensionVariables';
|
||||
import { localize } from './utils/localize';
|
||||
import { getWorkspaceSetting, updateGlobalSetting } from './utils/settingUtils';
|
||||
import { getNodeEditorLabel } from './utils/vscodeUtils';
|
||||
|
||||
export interface IEditableTreeItem extends AzExtTreeItem {
|
||||
id: string;
|
||||
|
@ -34,14 +40,30 @@ export class DatabasesFileSystem extends AzExtTreeFileSystem<IEditableTreeItem>
|
|||
return Buffer.from(await node.getFileContent(context));
|
||||
}
|
||||
|
||||
public async writeFileImpl(context: IActionContext, node: IEditableTreeItem, content: Uint8Array, _originalUri: Uri): Promise<void> {
|
||||
public async writeFileImpl(
|
||||
context: IActionContext,
|
||||
node: IEditableTreeItem,
|
||||
content: Uint8Array,
|
||||
_originalUri: Uri,
|
||||
): Promise<void> {
|
||||
const showSavePromptKey: string = 'showSavePrompt';
|
||||
// NOTE: Using "cosmosDB" instead of "azureDatabases" here for the sake of backwards compatibility. If/when this file system adds support for non-cosmosdb items, we should consider changing this to "azureDatabases"
|
||||
const prefix: string = 'cosmosDB';
|
||||
const nodeEditorLabel: string = getNodeEditorLabel(node);
|
||||
if (this._showSaveConfirmation && getWorkspaceSetting<boolean>(showSavePromptKey, undefined, prefix)) {
|
||||
const message: string = localize('saveConfirmation', 'Saving "{0}" will update the entity "{1}" to the cloud.', node.filePath, nodeEditorLabel);
|
||||
const result: MessageItem | undefined = await context.ui.showWarningMessage(message, { stepName: 'writeFile' }, DialogResponses.upload, DialogResponses.alwaysUpload, DialogResponses.dontUpload);
|
||||
const message: string = localize(
|
||||
'saveConfirmation',
|
||||
'Saving "{0}" will update the entity "{1}" to the cloud.',
|
||||
node.filePath,
|
||||
nodeEditorLabel,
|
||||
);
|
||||
const result: MessageItem | undefined = await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ stepName: 'writeFile' },
|
||||
DialogResponses.upload,
|
||||
DialogResponses.alwaysUpload,
|
||||
DialogResponses.dontUpload,
|
||||
);
|
||||
if (result === DialogResponses.alwaysUpload) {
|
||||
await updateGlobalSetting(showSavePromptKey, false, prefix);
|
||||
} else if (result === DialogResponses.dontUpload) {
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtServiceClientCredentials } from "@microsoft/vscode-azext-utils";
|
||||
import { type AzExtServiceClientCredentials } from '@microsoft/vscode-azext-utils';
|
||||
|
||||
/**
|
||||
* Gets a function that can request an access token for a specified scope for the signed-in azure account.
|
||||
*/
|
||||
export function getTokenFunction(credentials: AzExtServiceClientCredentials, scope: string): () => Promise<string> {
|
||||
return async () => {
|
||||
const getTokenResult = await credentials.getToken(scope) as { token: string } | undefined;
|
||||
return getTokenResult?.token ?? "";
|
||||
const getTokenResult = (await credentials.getToken(scope)) as { token: string } | undefined;
|
||||
return getTokenResult?.token ?? '';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,24 +3,27 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { API } from '../../AzureDBExperiences';
|
||||
import { getCosmosKeyCredential } from '../../docdb/getCosmosClient';
|
||||
import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings';
|
||||
import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem';
|
||||
import { ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { type ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { ParsedPostgresConnectionString } from '../../postgres/postgresConnectionStrings';
|
||||
import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api';
|
||||
import { type DatabaseAccountTreeItem } from '../../vscode-cosmosdb.api';
|
||||
|
||||
export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem {
|
||||
protected _parsedCS: ParsedConnectionString;
|
||||
private _accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem | undefined;
|
||||
|
||||
constructor(parsedCS: ParsedConnectionString, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem) {
|
||||
constructor(
|
||||
parsedCS: ParsedConnectionString,
|
||||
accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem,
|
||||
) {
|
||||
this._parsedCS = parsedCS;
|
||||
this._accountNode = accountNode;
|
||||
}
|
||||
|
@ -37,32 +40,35 @@ export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem
|
|||
return this._parsedCS.port;
|
||||
}
|
||||
|
||||
public get azureData(): { accountName: string, accountId: string } | undefined {
|
||||
if (this._accountNode instanceof MongoAccountTreeItem || this._accountNode instanceof DocDBAccountTreeItemBase) {
|
||||
public get azureData(): { accountName: string; accountId: string } | undefined {
|
||||
if (
|
||||
this._accountNode instanceof MongoAccountTreeItem ||
|
||||
this._accountNode instanceof DocDBAccountTreeItemBase
|
||||
) {
|
||||
if (this._accountNode?.databaseAccount) {
|
||||
return {
|
||||
accountName: nonNullProp(this._accountNode.databaseAccount, 'name'),
|
||||
accountId: this._accountNode.fullId
|
||||
accountId: this._accountNode.fullId,
|
||||
};
|
||||
}
|
||||
} else if (this._accountNode instanceof PostgresServerTreeItem) {
|
||||
if (this._accountNode.azureName) {
|
||||
return {
|
||||
accountName: this._accountNode.azureName,
|
||||
accountId: this._accountNode.fullId
|
||||
accountId: this._accountNode.fullId,
|
||||
};
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public get docDBData(): { masterKey: string; documentEndpoint: string; } | undefined {
|
||||
public get docDBData(): { masterKey: string; documentEndpoint: string } | undefined {
|
||||
if (this._accountNode instanceof DocDBAccountTreeItemBase) {
|
||||
const keyCred = getCosmosKeyCredential(this._accountNode.root.credentials);
|
||||
if (keyCred) {
|
||||
return {
|
||||
documentEndpoint: this._accountNode.root.endpoint,
|
||||
masterKey: keyCred.key
|
||||
masterKey: keyCred.key,
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
|
@ -77,7 +83,7 @@ export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem
|
|||
const connectionString = this._parsedCS;
|
||||
return {
|
||||
username: connectionString.username,
|
||||
password: connectionString.password
|
||||
password: connectionString.password,
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
|
@ -92,10 +98,11 @@ export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem
|
|||
});
|
||||
}
|
||||
|
||||
protected async getAccountNode(context: IActionContext): Promise<MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem> {
|
||||
protected async getAccountNode(
|
||||
context: IActionContext,
|
||||
): Promise<MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem> {
|
||||
// If this._accountNode is undefined, attach a new node based on connection string
|
||||
if (!this._accountNode) {
|
||||
|
||||
let apiType: API;
|
||||
if (this._parsedCS instanceof ParsedMongoConnectionString) {
|
||||
apiType = API.MongoDB;
|
||||
|
@ -104,7 +111,11 @@ export class DatabaseAccountTreeItemInternal implements DatabaseAccountTreeItem
|
|||
} else {
|
||||
apiType = API.Core;
|
||||
}
|
||||
this._accountNode = await ext.attachedAccountsNode.attachConnectionString(context, this.connectionString, apiType);
|
||||
this._accountNode = await ext.attachedAccountsNode.attachConnectionString(
|
||||
context,
|
||||
this.connectionString,
|
||||
apiType,
|
||||
);
|
||||
}
|
||||
|
||||
return this._accountNode;
|
||||
|
|
|
@ -3,23 +3,32 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase';
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { type DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { type DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem';
|
||||
import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem';
|
||||
import { ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem';
|
||||
import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem';
|
||||
import { DatabaseTreeItem } from '../../vscode-cosmosdb.api';
|
||||
import { type MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem';
|
||||
import { type MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem';
|
||||
import { type ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { type PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem';
|
||||
import { type PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem';
|
||||
import { type DatabaseTreeItem } from '../../vscode-cosmosdb.api';
|
||||
import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal';
|
||||
|
||||
export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal implements DatabaseTreeItem {
|
||||
public databaseName: string;
|
||||
private _dbNode: AzExtTreeItem | undefined;
|
||||
|
||||
constructor(parsedCS: ParsedConnectionString, databaseName: string, accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem, dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem) {
|
||||
constructor(
|
||||
parsedCS: ParsedConnectionString,
|
||||
databaseName: string,
|
||||
accountNode?: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem,
|
||||
dbNode?: MongoDatabaseTreeItem | DocDBDatabaseTreeItemBase | PostgresDatabaseTreeItem,
|
||||
) {
|
||||
super(parsedCS, accountNode);
|
||||
this.databaseName = databaseName;
|
||||
this._dbNode = dbNode;
|
||||
|
@ -30,7 +39,8 @@ export class DatabaseTreeItemInternal extends DatabaseAccountTreeItemInternal im
|
|||
context.errorHandling.suppressDisplay = true;
|
||||
context.errorHandling.rethrow = true;
|
||||
|
||||
const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem = await this.getAccountNode(context);
|
||||
const accountNode: MongoAccountTreeItem | DocDBAccountTreeItemBase | PostgresServerTreeItem =
|
||||
await this.getAccountNode(context);
|
||||
if (!this._dbNode) {
|
||||
const databaseId = `${accountNode.fullId}/${this.databaseName}`;
|
||||
this._dbNode = await ext.rgApi.workspaceResourceTree.findTreeItem(databaseId, context);
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
|
||||
import { ParsedDocDBConnectionString } from '../../docdb/docDBConnectionStrings';
|
||||
import { ParsedMongoConnectionString } from '../../mongo/mongoConnectionStrings';
|
||||
import { ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { ParsedPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings';
|
||||
import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb.api';
|
||||
import { type ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import {
|
||||
ParsedPostgresConnectionString,
|
||||
parsePostgresConnectionString,
|
||||
} from '../../postgres/postgresConnectionStrings';
|
||||
import { type DatabaseAccountTreeItem, type DatabaseTreeItem } from '../../vscode-cosmosdb.api';
|
||||
|
||||
/**
|
||||
* This cache is used to speed up api calls from other extensions to the Cosmos DB extension
|
||||
|
@ -16,11 +19,16 @@ import { DatabaseAccountTreeItem, DatabaseTreeItem } from '../../vscode-cosmosdb
|
|||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const sessionCache: Map<string, DatabaseAccountTreeItem | DatabaseTreeItem> = new Map();
|
||||
|
||||
export function cacheTreeItem(parsedCS: ParsedConnectionString, treeItem: DatabaseAccountTreeItem | DatabaseTreeItem): void {
|
||||
export function cacheTreeItem(
|
||||
parsedCS: ParsedConnectionString,
|
||||
treeItem: DatabaseAccountTreeItem | DatabaseTreeItem,
|
||||
): void {
|
||||
sessionCache.set(parsedCS.fullId, treeItem);
|
||||
}
|
||||
|
||||
export function tryGetTreeItemFromCache(parsedCS: ParsedConnectionString): DatabaseAccountTreeItem | DatabaseTreeItem | undefined {
|
||||
export function tryGetTreeItemFromCache(
|
||||
parsedCS: ParsedConnectionString,
|
||||
): DatabaseAccountTreeItem | DatabaseTreeItem | undefined {
|
||||
return sessionCache.get(parsedCS.fullId);
|
||||
}
|
||||
|
||||
|
@ -36,7 +44,7 @@ export function removeTreeItemFromCache(expected: ParsedConnectionString): void
|
|||
} else {
|
||||
actual = new ParsedDocDBConnectionString(value.connectionString, value.hostName, value.port, undefined);
|
||||
}
|
||||
if (actual && (actual.accountId === expected.accountId)) {
|
||||
if (actual && actual.accountId === expected.accountId) {
|
||||
sessionCache.delete(key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings';
|
||||
import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase';
|
||||
|
@ -11,18 +15,23 @@ import { ext } from '../../extensionVariables';
|
|||
import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings';
|
||||
import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem';
|
||||
import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem';
|
||||
import { ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { createPostgresConnectionString, parsePostgresConnectionString } from '../../postgres/postgresConnectionStrings';
|
||||
import { type ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import {
|
||||
createPostgresConnectionString,
|
||||
parsePostgresConnectionString,
|
||||
} from '../../postgres/postgresConnectionStrings';
|
||||
import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem';
|
||||
import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem';
|
||||
import { SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DatabaseAccountTreeItem, DatabaseTreeItem, TreeItemQuery } from '../../vscode-cosmosdb.api';
|
||||
import { type DatabaseAccountTreeItem, type DatabaseTreeItem, type TreeItemQuery } from '../../vscode-cosmosdb.api';
|
||||
import { cacheTreeItem, tryGetTreeItemFromCache } from './apiCache';
|
||||
import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal';
|
||||
import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal';
|
||||
|
||||
export async function findTreeItem(query: TreeItemQuery): Promise<DatabaseAccountTreeItem | DatabaseTreeItem | undefined> {
|
||||
export async function findTreeItem(
|
||||
query: TreeItemQuery,
|
||||
): Promise<DatabaseAccountTreeItem | DatabaseTreeItem | undefined> {
|
||||
return await callWithTelemetryAndErrorHandling('api.findTreeItem', async (context: IActionContext) => {
|
||||
context.errorHandling.suppressDisplay = true;
|
||||
context.errorHandling.rethrow = true;
|
||||
|
@ -30,7 +39,13 @@ export async function findTreeItem(query: TreeItemQuery): Promise<DatabaseAccoun
|
|||
let parsedCS: ParsedConnectionString;
|
||||
if (query.postgresData) {
|
||||
const postgresData = query.postgresData;
|
||||
const connectionString: string = createPostgresConnectionString(postgresData.hostName, postgresData.port, postgresData.username, postgresData.password, postgresData.databaseName);
|
||||
const connectionString: string = createPostgresConnectionString(
|
||||
postgresData.hostName,
|
||||
postgresData.port,
|
||||
postgresData.username,
|
||||
postgresData.password,
|
||||
postgresData.databaseName,
|
||||
);
|
||||
parsedCS = parsePostgresConnectionString(connectionString);
|
||||
} else {
|
||||
const connectionString = nonNullProp(query, 'connectionString');
|
||||
|
@ -87,7 +102,12 @@ export async function findTreeItem(query: TreeItemQuery): Promise<DatabaseAccoun
|
|||
});
|
||||
}
|
||||
|
||||
async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedConnectionString, context: IActionContext, maxTime: number): Promise<DatabaseAccountTreeItem | DatabaseTreeItem | undefined> {
|
||||
async function searchDbAccounts(
|
||||
dbAccounts: AzExtTreeItem[],
|
||||
expected: ParsedConnectionString,
|
||||
context: IActionContext,
|
||||
maxTime: number,
|
||||
): Promise<DatabaseAccountTreeItem | DatabaseTreeItem | undefined> {
|
||||
try {
|
||||
for (const dbAccount of dbAccounts) {
|
||||
if (Date.now() > maxTime) {
|
||||
|
@ -109,12 +129,24 @@ async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedCon
|
|||
if (expected.databaseName) {
|
||||
const dbs = await dbAccount.getCachedChildren(context);
|
||||
for (const db of dbs) {
|
||||
if ((db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) && expected.databaseName === db.databaseName) {
|
||||
if (
|
||||
(db instanceof MongoDatabaseTreeItem || db instanceof DocDBDatabaseTreeItemBase) &&
|
||||
expected.databaseName === db.databaseName
|
||||
) {
|
||||
return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount, db);
|
||||
}
|
||||
if ((db instanceof PostgresDatabaseTreeItem && dbAccount instanceof PostgresServerTreeItem) && expected.databaseName === db.databaseName) {
|
||||
if (
|
||||
db instanceof PostgresDatabaseTreeItem &&
|
||||
dbAccount instanceof PostgresServerTreeItem &&
|
||||
expected.databaseName === db.databaseName
|
||||
) {
|
||||
const fullConnectionString = await dbAccount.getFullConnectionString();
|
||||
return new DatabaseTreeItemInternal(fullConnectionString, expected.databaseName, dbAccount, db);
|
||||
return new DatabaseTreeItemInternal(
|
||||
fullConnectionString,
|
||||
expected.databaseName,
|
||||
dbAccount,
|
||||
db,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +157,6 @@ async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedCon
|
|||
} else {
|
||||
return new DatabaseTreeItemInternal(expected, expected.databaseName, dbAccount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dbAccount instanceof PostgresServerTreeItem) {
|
||||
|
@ -134,10 +165,9 @@ async function searchDbAccounts(dbAccounts: AzExtTreeItem[], expected: ParsedCon
|
|||
} else {
|
||||
return new DatabaseAccountTreeItemInternal(expected, dbAccount);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Swallow all errors to avoid blocking the db account search
|
||||
// https://github.com/microsoft/vscode-cosmosdb/issues/966
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { callWithTelemetryAndErrorHandling, IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi';
|
||||
import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { type PickAppResourceOptions } from '@microsoft/vscode-azext-utils/hostapi';
|
||||
import { databaseAccountType } from '../../constants';
|
||||
import { parseDocDBConnectionString } from '../../docdb/docDBConnectionStrings';
|
||||
import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
|
@ -15,16 +15,26 @@ import { GraphDatabaseTreeItem } from '../../graph/tree/GraphDatabaseTreeItem';
|
|||
import { parseMongoConnectionString } from '../../mongo/mongoConnectionStrings';
|
||||
import { MongoAccountTreeItem } from '../../mongo/tree/MongoAccountTreeItem';
|
||||
import { MongoDatabaseTreeItem } from '../../mongo/tree/MongoDatabaseTreeItem';
|
||||
import { ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { type ParsedConnectionString } from '../../ParsedConnectionString';
|
||||
import { PostgresDatabaseTreeItem } from '../../postgres/tree/PostgresDatabaseTreeItem';
|
||||
import { PostgresServerTreeItem } from '../../postgres/tree/PostgresServerTreeItem';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { AzureDatabasesApiType, DatabaseAccountTreeItem, DatabaseTreeItem, PickTreeItemOptions } from '../../vscode-cosmosdb.api';
|
||||
import {
|
||||
type AzureDatabasesApiType,
|
||||
type DatabaseAccountTreeItem,
|
||||
type DatabaseTreeItem,
|
||||
type PickTreeItemOptions,
|
||||
} from '../../vscode-cosmosdb.api';
|
||||
import { cacheTreeItem } from './apiCache';
|
||||
import { DatabaseAccountTreeItemInternal } from './DatabaseAccountTreeItemInternal';
|
||||
import { DatabaseTreeItemInternal } from './DatabaseTreeItemInternal';
|
||||
|
||||
const databaseContextValues = [MongoDatabaseTreeItem.contextValue, DocDBDatabaseTreeItem.contextValue, GraphDatabaseTreeItem.contextValue, PostgresDatabaseTreeItem.contextValue];
|
||||
const databaseContextValues = [
|
||||
MongoDatabaseTreeItem.contextValue,
|
||||
DocDBDatabaseTreeItem.contextValue,
|
||||
GraphDatabaseTreeItem.contextValue,
|
||||
PostgresDatabaseTreeItem.contextValue,
|
||||
];
|
||||
function getDatabaseContextValue(apiType: AzureDatabasesApiType): string {
|
||||
switch (apiType) {
|
||||
case 'Mongo':
|
||||
|
@ -40,8 +50,9 @@ function getDatabaseContextValue(apiType: AzureDatabasesApiType): string {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promise<DatabaseTreeItem | DatabaseAccountTreeItem | undefined> {
|
||||
export async function pickTreeItem(
|
||||
pickTreeOptions: PickTreeItemOptions,
|
||||
): Promise<DatabaseTreeItem | DatabaseAccountTreeItem | undefined> {
|
||||
return await callWithTelemetryAndErrorHandling('api.pickTreeItem', async (context: IActionContext) => {
|
||||
context.errorHandling.suppressDisplay = true;
|
||||
context.errorHandling.rethrow = true;
|
||||
|
@ -50,9 +61,9 @@ export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promis
|
|||
switch (pickTreeOptions.resourceType) {
|
||||
case 'Database':
|
||||
options.filter = { type: databaseAccountType };
|
||||
options.expectedChildContextValue = pickTreeOptions.apiType ?
|
||||
pickTreeOptions.apiType.map(getDatabaseContextValue) :
|
||||
databaseContextValues;
|
||||
options.expectedChildContextValue = pickTreeOptions.apiType
|
||||
? pickTreeOptions.apiType.map(getDatabaseContextValue)
|
||||
: databaseContextValues;
|
||||
break;
|
||||
case 'DatabaseAccount':
|
||||
options.filter = { type: databaseAccountType };
|
||||
|
@ -91,9 +102,9 @@ export async function pickTreeItem(pickTreeOptions: PickTreeItemOptions): Promis
|
|||
throw new RangeError(localize('invalidItem', 'Invalid item "{0}".', pickedItem.constructor.name));
|
||||
}
|
||||
|
||||
const result = databaseNode ?
|
||||
new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode) :
|
||||
new DatabaseAccountTreeItemInternal(parsedCS, accountNode);
|
||||
const result = databaseNode
|
||||
? new DatabaseTreeItemInternal(parsedCS, databaseNode.databaseName, accountNode, databaseNode)
|
||||
: new DatabaseAccountTreeItemInternal(parsedCS, accountNode);
|
||||
cacheTreeItem(parsedCS, result);
|
||||
return result;
|
||||
});
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { ext } from '../../extensionVariables';
|
||||
|
||||
export async function revealTreeItem(resourceId: string): Promise<void> {
|
||||
return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => {
|
||||
const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, { ...context, loadAll: true });
|
||||
const node: AzExtTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(resourceId, {
|
||||
...context,
|
||||
loadAll: true,
|
||||
});
|
||||
if (node) {
|
||||
await ext.rgApi.appResourceTreeView.reveal(node, { select: true, focus: true, expand: true });
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzureWizardExecuteStep } from "@microsoft/vscode-azext-utils";
|
||||
import { IDeleteWizardContext } from "./IDeleteWizardContext";
|
||||
import { AzureWizardExecuteStep } from '@microsoft/vscode-azext-utils';
|
||||
import { type IDeleteWizardContext } from './IDeleteWizardContext';
|
||||
|
||||
export class DatabaseAccountDeleteStep extends AzureWizardExecuteStep<IDeleteWizardContext> {
|
||||
public priority: number = 100;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, ExecuteActivityContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils";
|
||||
import {
|
||||
type AzExtTreeItem,
|
||||
type ExecuteActivityContext,
|
||||
type IActionContext,
|
||||
type ISubscriptionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
|
||||
export interface IDeleteWizardContext extends IActionContext, ExecuteActivityContext {
|
||||
node: AzExtTreeItem;
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosDBManagementClient } from '@azure/arm-cosmosdb';
|
||||
import { type CosmosDBManagementClient } from '@azure/arm-cosmosdb';
|
||||
import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils';
|
||||
import { AzExtTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import { type AzExtTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { createCosmosDBClient } from '../../utils/azureClients';
|
||||
import { getDatabaseAccountNameFromId } from '../../utils/azureUtils';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { IDeleteWizardContext } from './IDeleteWizardContext';
|
||||
import { type IDeleteWizardContext } from './IDeleteWizardContext';
|
||||
|
||||
export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node: AzExtTreeItem): Promise<void> {
|
||||
const client: CosmosDBManagementClient = await createCosmosDBClient([context, node.subscription]);
|
||||
|
@ -20,12 +20,19 @@ export async function deleteCosmosDBAccount(context: IDeleteWizardContext, node:
|
|||
const deletePromise = client.databaseAccounts.beginDeleteAndWait(resourceGroup, accountName);
|
||||
if (!context.suppressNotification) {
|
||||
const deletingMessage: string = `Deleting account "${accountName}"...`;
|
||||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: deletingMessage }, async () => {
|
||||
await deletePromise;
|
||||
const deleteMessage: string = localize("deleteAccountMsg", `Successfully deleted account "{0}".`, accountName);
|
||||
void vscode.window.showInformationMessage(deleteMessage);
|
||||
ext.outputChannel.appendLog(deleteMessage);
|
||||
});
|
||||
await vscode.window.withProgress(
|
||||
{ location: vscode.ProgressLocation.Notification, title: deletingMessage },
|
||||
async () => {
|
||||
await deletePromise;
|
||||
const deleteMessage: string = localize(
|
||||
'deleteAccountMsg',
|
||||
`Successfully deleted account "{0}".`,
|
||||
accountName,
|
||||
);
|
||||
void vscode.window.showInformationMessage(deleteMessage);
|
||||
ext.outputChannel.appendLog(deleteMessage);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
await deletePromise;
|
||||
}
|
||||
|
|
|
@ -3,33 +3,45 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { createActivityContext } from "../../utils/activityUtils";
|
||||
import { localize } from "../../utils/localize";
|
||||
import { DatabaseAccountDeleteStep } from "./DatabaseAccountDeleteStep";
|
||||
import { IDeleteWizardContext } from "./IDeleteWizardContext";
|
||||
import {
|
||||
AzureWizard,
|
||||
DeleteConfirmationStep,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { createActivityContext } from '../../utils/activityUtils';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { DatabaseAccountDeleteStep } from './DatabaseAccountDeleteStep';
|
||||
import { type IDeleteWizardContext } from './IDeleteWizardContext';
|
||||
|
||||
|
||||
export async function deleteDatabaseAccount(context: IActionContext, node: AzExtTreeItem, isPostgres: boolean = false): Promise<void> {
|
||||
export async function deleteDatabaseAccount(
|
||||
context: IActionContext,
|
||||
node: AzExtTreeItem,
|
||||
isPostgres: boolean = false,
|
||||
): Promise<void> {
|
||||
const wizardContext: IDeleteWizardContext = Object.assign(context, {
|
||||
node,
|
||||
deletePostgres: isPostgres,
|
||||
subscription: node.subscription,
|
||||
...(await createActivityContext())
|
||||
...(await createActivityContext()),
|
||||
});
|
||||
|
||||
const title = wizardContext.deletePostgres ?
|
||||
localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label) :
|
||||
localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label)
|
||||
const title = wizardContext.deletePostgres
|
||||
? localize('deletePoSer', 'Delete Postgres Server "{0}"', node.label)
|
||||
: localize('deleteDbAcc', 'Delete Database Account "{0}"', node.label);
|
||||
|
||||
const confirmationMessage = wizardContext.deletePostgres ?
|
||||
localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label) :
|
||||
localize('deleteAccountConfirm', 'Are you sure you want to delete account "{0}" and its contents?', node.label);
|
||||
const confirmationMessage = wizardContext.deletePostgres
|
||||
? localize('deleteAccountConfirm', 'Are you sure you want to delete server "{0}" and its contents?', node.label)
|
||||
: localize(
|
||||
'deleteAccountConfirm',
|
||||
'Are you sure you want to delete account "{0}" and its contents?',
|
||||
node.label,
|
||||
);
|
||||
|
||||
const wizard = new AzureWizard(wizardContext, {
|
||||
title,
|
||||
promptSteps: [new DeleteConfirmationStep(confirmationMessage)],
|
||||
executeSteps: [new DatabaseAccountDeleteStep()]
|
||||
executeSteps: [new DatabaseAccountDeleteStep()],
|
||||
});
|
||||
|
||||
await wizard.prompt();
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ItemDefinition } from '@azure/cosmos';
|
||||
import { IActionContext, parseError } from '@microsoft/vscode-azext-utils';
|
||||
import { type ItemDefinition } from '@azure/cosmos';
|
||||
import { parseError, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as fse from 'fs-extra';
|
||||
import * as vscode from 'vscode';
|
||||
import { cosmosMongoFilter, sqlFilter } from '../constants';
|
||||
|
@ -14,7 +14,11 @@ import { MongoCollectionTreeItem } from '../mongo/tree/MongoCollectionTreeItem';
|
|||
import { nonNullProp, nonNullValue } from '../utils/nonNull';
|
||||
import { getRootPath } from '../utils/workspacUtils';
|
||||
|
||||
export async function importDocuments(context: IActionContext, uris: vscode.Uri[] | undefined, collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined): Promise<void> {
|
||||
export async function importDocuments(
|
||||
context: IActionContext,
|
||||
uris: vscode.Uri[] | undefined,
|
||||
collectionNode: MongoCollectionTreeItem | DocDBCollectionTreeItem | undefined,
|
||||
): Promise<void> {
|
||||
if (!uris) {
|
||||
uris = await askForDocuments(context);
|
||||
}
|
||||
|
@ -29,39 +33,36 @@ export async function importDocuments(context: IActionContext, uris: vscode.Uri[
|
|||
});
|
||||
if (ignoredUris.length) {
|
||||
ext.outputChannel.appendLog(`Ignoring the following files which are not json:`);
|
||||
ignoredUris.forEach(uri => ext.outputChannel.appendLog(`${uri.fsPath}`));
|
||||
ignoredUris.forEach((uri) => ext.outputChannel.appendLog(`${uri.fsPath}`));
|
||||
ext.outputChannel.show();
|
||||
}
|
||||
if (!collectionNode) {
|
||||
collectionNode = await ext.rgApi.pickAppResource<MongoCollectionTreeItem | DocDBCollectionTreeItem>(context, {
|
||||
filter: [
|
||||
cosmosMongoFilter,
|
||||
sqlFilter
|
||||
],
|
||||
expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue]
|
||||
filter: [cosmosMongoFilter, sqlFilter],
|
||||
expectedChildContextValue: [MongoCollectionTreeItem.contextValue, DocDBCollectionTreeItem.contextValue],
|
||||
});
|
||||
}
|
||||
let result: string;
|
||||
result = await vscode.window.withProgress(
|
||||
{
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: "Importing documents..."
|
||||
title: 'Importing documents...',
|
||||
},
|
||||
async (progress) => {
|
||||
uris = nonNullValue(uris, 'uris');
|
||||
collectionNode = nonNullValue(collectionNode, 'collectionNode');
|
||||
|
||||
progress.report({ increment: 20, message: "Parsing documents for errors" });
|
||||
progress.report({ increment: 20, message: 'Parsing documents for errors' });
|
||||
const documents = await parseDocuments(uris);
|
||||
progress.report({ increment: 30, message: "Parsed documents. Importing" });
|
||||
progress.report({ increment: 30, message: 'Parsed documents. Importing' });
|
||||
if (collectionNode instanceof MongoCollectionTreeItem) {
|
||||
result = await insertDocumentsIntoMongo(collectionNode, documents);
|
||||
} else {
|
||||
result = await insertDocumentsIntoDocdb(collectionNode, documents, uris);
|
||||
}
|
||||
progress.report({ increment: 50, message: "Finished importing" });
|
||||
progress.report({ increment: 50, message: 'Finished importing' });
|
||||
return result;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await collectionNode.refresh(context);
|
||||
|
@ -71,10 +72,10 @@ export async function importDocuments(context: IActionContext, uris: vscode.Uri[
|
|||
async function askForDocuments(context: IActionContext): Promise<vscode.Uri[]> {
|
||||
const openDialogOptions: vscode.OpenDialogOptions = {
|
||||
canSelectMany: true,
|
||||
openLabel: "Import",
|
||||
openLabel: 'Import',
|
||||
filters: {
|
||||
JSON: ["json"]
|
||||
}
|
||||
JSON: ['json'],
|
||||
},
|
||||
};
|
||||
const rootPath: string | undefined = getRootPath();
|
||||
if (rootPath) {
|
||||
|
@ -96,7 +97,7 @@ async function parseDocuments(uris: vscode.Uri[]): Promise<any[]> {
|
|||
} catch (e) {
|
||||
if (!errorFoundFlag) {
|
||||
errorFoundFlag = true;
|
||||
ext.outputChannel.appendLog("Errors found in documents listed below. Please fix these.");
|
||||
ext.outputChannel.appendLog('Errors found in documents listed below. Please fix these.');
|
||||
ext.outputChannel.show();
|
||||
}
|
||||
const err = parseError(e);
|
||||
|
@ -118,8 +119,12 @@ async function parseDocuments(uris: vscode.Uri[]): Promise<any[]> {
|
|||
return documents;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem, documents: any[], uris: vscode.Uri[]): Promise<string> {
|
||||
async function insertDocumentsIntoDocdb(
|
||||
collectionNode: DocDBCollectionTreeItem,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
documents: any[],
|
||||
uris: vscode.Uri[],
|
||||
): Promise<string> {
|
||||
const ids: string[] = [];
|
||||
let i = 0;
|
||||
const erroneousFiles: vscode.Uri[] = [];
|
||||
|
@ -132,11 +137,14 @@ async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem,
|
|||
}
|
||||
if (erroneousFiles.length) {
|
||||
ext.outputChannel.appendLog(`The following documents do not contain the required partition key:`);
|
||||
erroneousFiles.forEach(file => ext.outputChannel.appendLog(file.path));
|
||||
erroneousFiles.forEach((file) => ext.outputChannel.appendLog(file.path));
|
||||
ext.outputChannel.show();
|
||||
throw new Error(`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`);
|
||||
throw new Error(
|
||||
`See output for list of documents that do not contain the partition key '${nonNullProp(collectionNode, 'partitionKey').paths[0]}' required by collection '${collectionNode.label}'`,
|
||||
);
|
||||
}
|
||||
for (const document of documents) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
const retrieved: ItemDefinition = await collectionNode.documentsTreeItem.createDocument(document);
|
||||
if (retrieved.id) {
|
||||
ids.push(retrieved.id);
|
||||
|
@ -151,7 +159,8 @@ async function insertDocumentsIntoDocdb(collectionNode: DocDBCollectionTreeItem,
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async function insertDocumentsIntoMongo(node: MongoCollectionTreeItem, documents: any[]): Promise<string> {
|
||||
let output = "";
|
||||
let output = '';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
const parsed = await node.collection.insertMany(documents);
|
||||
if (parsed.acknowledged) {
|
||||
output = `Import into mongo successful. Inserted ${parsed.insertedCount} document(s). See output for more details.`;
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface IThemedIconPath {
|
|||
export function getThemedIconPath(iconName: string): IThemedIconPath {
|
||||
const a = {
|
||||
light: path.join(getResourcesPath(), 'icons', 'light', iconName),
|
||||
dark: path.join(getResourcesPath(), 'icons', 'dark', iconName)
|
||||
dark: path.join(getResourcesPath(), 'icons', 'dark', iconName),
|
||||
};
|
||||
assert(fs.existsSync(a.light));
|
||||
return a;
|
||||
|
@ -32,7 +32,7 @@ export function getThemedIconPath(iconName: string): IThemedIconPath {
|
|||
export function getThemeAgnosticIconPath(iconName: string): IThemedIconPath {
|
||||
const a = {
|
||||
light: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName),
|
||||
dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName)
|
||||
dark: path.join(getResourcesPath(), 'icons', 'theme-agnostic', iconName),
|
||||
};
|
||||
assert(fs.existsSync(a.light));
|
||||
return a;
|
||||
|
@ -44,8 +44,7 @@ export function getResourcesPath(): string {
|
|||
|
||||
export const doubleClickDebounceDelay = 500; //milliseconds
|
||||
|
||||
export const defaultStoredProcedure =
|
||||
`function sample(prefix) {
|
||||
export const defaultStoredProcedure = `function sample(prefix) {
|
||||
var collection = getContext().getCollection();
|
||||
|
||||
// Query documents and take 1st item.
|
||||
|
@ -70,13 +69,14 @@ export const defaultStoredProcedure =
|
|||
});
|
||||
|
||||
if (!isAccepted) throw new Error('The query was not accepted by the server.');
|
||||
};` ;
|
||||
};`;
|
||||
|
||||
export const defaultTrigger = `function trigger() {
|
||||
|
||||
}`;
|
||||
|
||||
export const emulatorPassword = 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==';
|
||||
export const emulatorPassword =
|
||||
'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==';
|
||||
|
||||
// https://docs.mongodb.com/manual/mongo/#working-with-the-mongo-shell
|
||||
export const testDb: string = 'test';
|
||||
|
@ -91,14 +91,14 @@ export const SERVERLESS_CAPABILITY_NAME = 'EnableServerless';
|
|||
|
||||
export const databaseAccountType = 'Microsoft.DocumentDB/databaseAccounts';
|
||||
|
||||
export const mongoDefaultExperienceTag = "Azure Cosmos DB for MongoDB API";
|
||||
export const mongoDefaultExperienceTag = 'Azure Cosmos DB for MongoDB API';
|
||||
|
||||
export const cosmosMongoFilter = {
|
||||
type: databaseAccountType,
|
||||
kind: MongoExperience.kind,
|
||||
tags: {
|
||||
defaultExperience: mongoDefaultExperienceTag
|
||||
}
|
||||
defaultExperience: mongoDefaultExperienceTag,
|
||||
},
|
||||
};
|
||||
|
||||
export const gremlinDefaultExperienceTag = 'Gremlin (graph)';
|
||||
|
@ -107,8 +107,8 @@ export const cosmosGremlinFilter = {
|
|||
type: databaseAccountType,
|
||||
kind: GremlinExperience.kind,
|
||||
tags: {
|
||||
defaultExperience: gremlinDefaultExperienceTag
|
||||
}
|
||||
defaultExperience: gremlinDefaultExperienceTag,
|
||||
},
|
||||
};
|
||||
|
||||
export const tableDefaultExperienceTag = 'Azure Table';
|
||||
|
@ -117,8 +117,8 @@ export const cosmosTableFilter = {
|
|||
type: databaseAccountType,
|
||||
kind: TableExperience.kind,
|
||||
tags: {
|
||||
defaultExperience: tableDefaultExperienceTag
|
||||
}
|
||||
defaultExperience: tableDefaultExperienceTag,
|
||||
},
|
||||
};
|
||||
|
||||
export const sqlDefaultExperienceTag = 'Core (SQL)';
|
||||
|
@ -127,14 +127,14 @@ export const sqlFilter = {
|
|||
type: databaseAccountType,
|
||||
kind: CoreExperience.kind,
|
||||
tags: {
|
||||
defaultExperience: sqlDefaultExperienceTag
|
||||
}
|
||||
defaultExperience: sqlDefaultExperienceTag,
|
||||
},
|
||||
};
|
||||
|
||||
export const postgresFlexibleFilter = {
|
||||
type: 'Microsoft.DBforPostgreSQL/flexibleServers'
|
||||
type: 'Microsoft.DBforPostgreSQL/flexibleServers',
|
||||
};
|
||||
|
||||
export const postgresSingleFilter = {
|
||||
type: 'Microsoft.DBForPostgreSQL/servers'
|
||||
type: 'Microsoft.DBForPostgreSQL/servers',
|
||||
};
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, callWithTelemetryAndErrorHandling } from "@microsoft/vscode-azext-utils";
|
||||
import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
CancellationToken,
|
||||
CodeLens,
|
||||
CodeLensProvider,
|
||||
Event,
|
||||
EventEmitter,
|
||||
Position,
|
||||
ProviderResult,
|
||||
Range,
|
||||
TextDocument
|
||||
} from "vscode";
|
||||
import { KeyValueStore } from "../KeyValueStore";
|
||||
type CancellationToken,
|
||||
type CodeLensProvider,
|
||||
type Event,
|
||||
type ProviderResult,
|
||||
type TextDocument,
|
||||
} from 'vscode';
|
||||
import { KeyValueStore } from '../KeyValueStore';
|
||||
|
||||
export type NoSqlQueryConnection = {
|
||||
databaseId: string;
|
||||
|
@ -25,7 +25,7 @@ export type NoSqlQueryConnection = {
|
|||
isEmulator: boolean;
|
||||
};
|
||||
|
||||
export const noSqlQueryConnectionKey = "NO_SQL_QUERY_CONNECTION_KEY.v1";
|
||||
export const noSqlQueryConnectionKey = 'NO_SQL_QUERY_CONNECTION_KEY.v1';
|
||||
|
||||
export class NoSqlCodeLensProvider implements CodeLensProvider {
|
||||
private _onDidChangeEmitter: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
@ -39,59 +39,46 @@ export class NoSqlCodeLensProvider implements CodeLensProvider {
|
|||
}
|
||||
|
||||
public provideCodeLenses(document: TextDocument, _token: CancellationToken): ProviderResult<CodeLens[]> {
|
||||
return callWithTelemetryAndErrorHandling("nosql.provideCodeLenses", (context: IActionContext) => {
|
||||
return callWithTelemetryAndErrorHandling('nosql.provideCodeLenses', (context: IActionContext) => {
|
||||
context.telemetry.suppressIfSuccessful = true;
|
||||
const text = document.getText();
|
||||
const queryText = text;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
||||
const connectedCollection: NoSqlQueryConnection | undefined = KeyValueStore.instance.get(noSqlQueryConnectionKey) as any;
|
||||
const connectedCollection: NoSqlQueryConnection | undefined = KeyValueStore.instance.get(
|
||||
noSqlQueryConnectionKey,
|
||||
) as unknown as NoSqlQueryConnection;
|
||||
let connectCodeLens: CodeLens;
|
||||
if (!connectedCollection) {
|
||||
connectCodeLens = new CodeLens(
|
||||
new Range(new Position(0, 0), new Position(0, 0)),
|
||||
{
|
||||
title: "Not connected",
|
||||
command: "cosmosDB.connectNoSqlContainer",
|
||||
arguments: []
|
||||
}
|
||||
);
|
||||
connectCodeLens = new CodeLens(new Range(new Position(0, 0), new Position(0, 0)), {
|
||||
title: 'Not connected',
|
||||
command: 'cosmosDB.connectNoSqlContainer',
|
||||
arguments: [],
|
||||
});
|
||||
} else {
|
||||
connectCodeLens = new CodeLens(
|
||||
new Range(new Position(0, 0), new Position(0, 0)),
|
||||
{
|
||||
title: `Connected to ${connectedCollection.databaseId}.${connectedCollection.containerId}`,
|
||||
command: "cosmosDB.connectNoSqlContainer",
|
||||
arguments: []
|
||||
}
|
||||
);
|
||||
connectCodeLens = new CodeLens(new Range(new Position(0, 0), new Position(0, 0)), {
|
||||
title: `Connected to ${connectedCollection.databaseId}.${connectedCollection.containerId}`,
|
||||
command: 'cosmosDB.connectNoSqlContainer',
|
||||
arguments: [],
|
||||
});
|
||||
}
|
||||
const lenses: CodeLens[] = [
|
||||
connectCodeLens,
|
||||
new CodeLens(
|
||||
new Range(new Position(0, 0), new Position(0, 0)),
|
||||
{
|
||||
title: "Execute",
|
||||
command: "cosmosDB.executeNoSqlQuery",
|
||||
arguments: [{ queryText }]
|
||||
}
|
||||
),
|
||||
new CodeLens(
|
||||
new Range(new Position(0, 0), new Position(0, 0)),
|
||||
{
|
||||
title: "Execute with Query Metrics",
|
||||
command: "cosmosDB.executeNoSqlQuery",
|
||||
arguments: [{ queryText, populateQueryMetrics: true }]
|
||||
}
|
||||
),
|
||||
new CodeLens(
|
||||
new Range(new Position(0, 0), new Position(0, 0)),
|
||||
{
|
||||
title: "Get Query Plan",
|
||||
command: "cosmosDB.getNoSqlQueryPlan",
|
||||
arguments: [{ queryText }]
|
||||
}
|
||||
)
|
||||
new CodeLens(new Range(new Position(0, 0), new Position(0, 0)), {
|
||||
title: 'Execute',
|
||||
command: 'cosmosDB.executeNoSqlQuery',
|
||||
arguments: [{ queryText }],
|
||||
}),
|
||||
new CodeLens(new Range(new Position(0, 0), new Position(0, 0)), {
|
||||
title: 'Execute with Query Metrics',
|
||||
command: 'cosmosDB.executeNoSqlQuery',
|
||||
arguments: [{ queryText, populateQueryMetrics: true }],
|
||||
}),
|
||||
new CodeLens(new Range(new Position(0, 0), new Position(0, 0)), {
|
||||
title: 'Get Query Plan',
|
||||
command: 'cosmosDB.getNoSqlQueryPlan',
|
||||
arguments: [{ queryText }],
|
||||
}),
|
||||
];
|
||||
|
||||
return lenses;
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { KeyValueStore } from "../../KeyValueStore";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { NoSqlQueryConnection, noSqlQueryConnectionKey } from "../NoSqlCodeLensProvider";
|
||||
import { getCosmosKeyCredential } from "../getCosmosClient";
|
||||
import { DocDBCollectionTreeItem } from "../tree/DocDBCollectionTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { KeyValueStore } from '../../KeyValueStore';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { noSqlQueryConnectionKey, type NoSqlQueryConnection } from '../NoSqlCodeLensProvider';
|
||||
import { getCosmosKeyCredential } from '../getCosmosClient';
|
||||
import { DocDBCollectionTreeItem } from '../tree/DocDBCollectionTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export function setConnectedNoSqlContainer(node: DocDBCollectionTreeItem): void {
|
||||
const root = node.root;
|
||||
|
@ -19,7 +19,7 @@ export function setConnectedNoSqlContainer(node: DocDBCollectionTreeItem): void
|
|||
containerId: node.id,
|
||||
endpoint: root.endpoint,
|
||||
masterKey: keyCred?.key,
|
||||
isEmulator: !!root.isEmulator
|
||||
isEmulator: !!root.isEmulator,
|
||||
};
|
||||
KeyValueStore.instance.set(noSqlQueryConnectionKey, noSqlQueryConnection);
|
||||
ext.noSqlCodeLensProvider.updateCodeLens();
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBDatabaseTreeItem } from "../tree/DocDBDatabaseTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBDatabaseTreeItem } from '../tree/DocDBDatabaseTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function createDocDBCollection(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBAccountTreeItem } from "../tree/DocDBAccountTreeItem";
|
||||
import { DocDBDatabaseTreeItem } from "../tree/DocDBDatabaseTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { type DocDBAccountTreeItem } from '../tree/DocDBAccountTreeItem';
|
||||
import { type DocDBDatabaseTreeItem } from '../tree/DocDBDatabaseTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function createDocDBDatabase(context: IActionContext, node?: DocDBAccountTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { commands } from "vscode";
|
||||
import { DocDBDocumentTreeItem } from "../tree/DocDBDocumentTreeItem";
|
||||
import { DocDBDocumentsTreeItem } from "../tree/DocDBDocumentsTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { commands } from 'vscode';
|
||||
import { type DocDBDocumentTreeItem } from '../tree/DocDBDocumentTreeItem';
|
||||
import { DocDBDocumentsTreeItem } from '../tree/DocDBDocumentsTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function createDocDBDocument(context: IActionContext, node?: DocDBDocumentsTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
node = await pickDocDBAccount<DocDBDocumentsTreeItem>(context, DocDBDocumentsTreeItem.contextValue);
|
||||
}
|
||||
const documentNode = <DocDBDocumentTreeItem>await node.createChild(context);
|
||||
await commands.executeCommand("cosmosDB.openDocument", documentNode);
|
||||
await commands.executeCommand('cosmosDB.openDocument', documentNode);
|
||||
}
|
||||
|
|
|
@ -3,15 +3,21 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { commands } from "vscode";
|
||||
import { DocDBStoredProceduresTreeItem } from "../tree/DocDBStoredProceduresTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { commands } from 'vscode';
|
||||
import { DocDBStoredProceduresTreeItem } from '../tree/DocDBStoredProceduresTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function createDocDBStoredProcedure(context: IActionContext, node?: DocDBStoredProceduresTreeItem): Promise<void> {
|
||||
export async function createDocDBStoredProcedure(
|
||||
context: IActionContext,
|
||||
node?: DocDBStoredProceduresTreeItem,
|
||||
): Promise<void> {
|
||||
if (!node) {
|
||||
node = await pickDocDBAccount<DocDBStoredProceduresTreeItem>(context, DocDBStoredProceduresTreeItem.contextValue);
|
||||
node = await pickDocDBAccount<DocDBStoredProceduresTreeItem>(
|
||||
context,
|
||||
DocDBStoredProceduresTreeItem.contextValue,
|
||||
);
|
||||
}
|
||||
const childNode = await node.createChild(context);
|
||||
await commands.executeCommand("cosmosDB.openStoredProcedure", childNode);
|
||||
await commands.executeCommand('cosmosDB.openStoredProcedure', childNode);
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { commands } from "vscode";
|
||||
import { DocDBTriggersTreeItem } from "../tree/DocDBTriggersTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { commands } from 'vscode';
|
||||
import { DocDBTriggersTreeItem } from '../tree/DocDBTriggersTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function createDocDBTrigger(context: IActionContext, node?: DocDBTriggersTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
node = await pickDocDBAccount<DocDBTriggersTreeItem>(context, DocDBTriggersTreeItem.contextValue);
|
||||
}
|
||||
const childNode = await node.createChild(context);
|
||||
await commands.executeCommand("cosmosDB.openTrigger", childNode);
|
||||
await commands.executeCommand('cosmosDB.openTrigger', childNode);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBCollectionTreeItem } from "../tree/DocDBCollectionTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBCollectionTreeItem } from '../tree/DocDBCollectionTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function deleteDocDBCollection(context: IActionContext, node?: DocDBCollectionTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { localize } from "../../utils/localize";
|
||||
import { DocDBDatabaseTreeItem } from "../tree/DocDBDatabaseTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { DocDBDatabaseTreeItem } from '../tree/DocDBDatabaseTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBDatabaseTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
@ -17,7 +17,7 @@ export async function deleteDocDBDatabase(context: IActionContext, node?: DocDBD
|
|||
node = await pickDocDBAccount<DocDBDatabaseTreeItem>(context, DocDBDatabaseTreeItem.contextValue);
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
const successMessage = localize("deleteMongoDatabaseMsg", 'Successfully deleted database "{0}"', node.databaseName);
|
||||
const successMessage = localize('deleteMongoDatabaseMsg', 'Successfully deleted database "{0}"', node.databaseName);
|
||||
void vscode.window.showInformationMessage(successMessage);
|
||||
ext.outputChannel.info(successMessage);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBDocumentTreeItem } from "../tree/DocDBDocumentTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBDocumentTreeItem } from '../tree/DocDBDocumentTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function deleteDocDBDocument(context: IActionContext, node?: DocDBDocumentTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBStoredProcedureTreeItem } from "../tree/DocDBStoredProcedureTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBStoredProcedureTreeItem } from '../tree/DocDBStoredProcedureTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function deleteDocDBStoredProcedure(context: IActionContext, node?: DocDBStoredProcedureTreeItem): Promise<void> {
|
||||
export async function deleteDocDBStoredProcedure(
|
||||
context: IActionContext,
|
||||
node?: DocDBStoredProcedureTreeItem,
|
||||
): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
|
|
|
@ -3,16 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { DocDBTriggerTreeItem } from "../tree/DocDBTriggerTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBTriggerTreeItem } from '../tree/DocDBTriggerTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function deleteDocDBTrigger(context: IActionContext, node?: DocDBTriggerTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await pickDocDBAccount<DocDBTriggerTreeItem>(context, DocDBTriggerTreeItem.contextValue);
|
||||
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
}
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { localize } from "../../utils/localize";
|
||||
import { DocDBStoredProcedureTreeItem } from "../tree/DocDBStoredProcedureTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { DocDBStoredProcedureTreeItem } from '../tree/DocDBStoredProcedureTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function executeDocDBStoredProcedure(context: IActionContext, node?: DocDBStoredProcedureTreeItem): Promise<void> {
|
||||
export async function executeDocDBStoredProcedure(
|
||||
context: IActionContext,
|
||||
node?: DocDBStoredProcedureTreeItem,
|
||||
): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
|
@ -22,15 +25,18 @@ export async function executeDocDBStoredProcedure(context: IActionContext, node?
|
|||
|
||||
const paramString = await context.ui.showInputBox({
|
||||
title: 'Parameters',
|
||||
placeHolder: localize("executeCosmosStoredProcedureParameters", "empty or array of values e.g. [1, {key: value}]"),
|
||||
placeHolder: localize(
|
||||
'executeCosmosStoredProcedureParameters',
|
||||
'empty or array of values e.g. [1, {key: value}]',
|
||||
),
|
||||
// @todo: add a learnMoreLink
|
||||
});
|
||||
|
||||
let parameters: (string | number | object)[] | undefined = undefined;
|
||||
if (paramString !== "") {
|
||||
if (paramString !== '') {
|
||||
try {
|
||||
parameters = JSON.parse(paramString) as (string | number | object)[];
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore parameters if they are invalid
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { ViewColumn } from "vscode";
|
||||
import { KeyValueStore } from "../../KeyValueStore";
|
||||
import { localize } from "../../utils/localize";
|
||||
import * as vscodeUtil from "../../utils/vscodeUtils";
|
||||
import { NoSqlQueryConnection, noSqlQueryConnectionKey } from "../NoSqlCodeLensProvider";
|
||||
import { CosmosDBCredential, getCosmosClient } from "../getCosmosClient";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ViewColumn } from 'vscode';
|
||||
import { KeyValueStore } from '../../KeyValueStore';
|
||||
import { localize } from '../../utils/localize';
|
||||
import * as vscodeUtil from '../../utils/vscodeUtils';
|
||||
import { noSqlQueryConnectionKey, type NoSqlQueryConnection } from '../NoSqlCodeLensProvider';
|
||||
import { getCosmosClient, type CosmosDBCredential } from '../getCosmosClient';
|
||||
|
||||
export async function executeNoSqlQuery(_context: IActionContext, args: { queryText: string, populateQueryMetrics?: boolean }): Promise<void> {
|
||||
export async function executeNoSqlQuery(
|
||||
_context: IActionContext,
|
||||
args: { queryText: string; populateQueryMetrics?: boolean },
|
||||
): Promise<void> {
|
||||
let queryText: string;
|
||||
let populateQueryMetrics: boolean;
|
||||
if (!args) {
|
||||
|
@ -29,26 +32,47 @@ export async function executeNoSqlQuery(_context: IActionContext, args: { queryT
|
|||
}
|
||||
const connectedCollection = KeyValueStore.instance.get(noSqlQueryConnectionKey);
|
||||
if (!connectedCollection) {
|
||||
throw new Error("Unable to execute query due to missing node data. Please connect to a Cosmos DB collection node.");
|
||||
throw new Error(
|
||||
'Unable to execute query due to missing node data. Please connect to a Cosmos DB collection node.',
|
||||
);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { databaseId, containerId, endpoint, masterKey, isEmulator } = connectedCollection as NoSqlQueryConnection;
|
||||
const { databaseId, containerId, endpoint, masterKey, isEmulator } =
|
||||
connectedCollection as NoSqlQueryConnection;
|
||||
const credentials: CosmosDBCredential[] = [];
|
||||
if (masterKey !== undefined) {
|
||||
credentials.push({ type: "key", key: masterKey });
|
||||
credentials.push({ type: 'key', key: masterKey });
|
||||
}
|
||||
credentials.push({ type: "auth" });
|
||||
credentials.push({ type: 'auth' });
|
||||
const client = getCosmosClient(endpoint, credentials, isEmulator);
|
||||
const options = { populateQueryMetrics };
|
||||
const response = await client.database(databaseId).container(containerId).items.query(queryText, options).fetchAll();
|
||||
const response = await client
|
||||
.database(databaseId)
|
||||
.container(containerId)
|
||||
.items.query(queryText, options)
|
||||
.fetchAll();
|
||||
const resultDocumentTitle = `query results for ${containerId}`;
|
||||
if (populateQueryMetrics === true) {
|
||||
await vscodeUtil.showNewFile(JSON.stringify({
|
||||
result: response.resources,
|
||||
queryMetrics: response.queryMetrics
|
||||
}, undefined, 2), resultDocumentTitle, ".json", ViewColumn.Beside);
|
||||
await vscodeUtil.showNewFile(
|
||||
JSON.stringify(
|
||||
{
|
||||
result: response.resources,
|
||||
queryMetrics: response.queryMetrics,
|
||||
},
|
||||
undefined,
|
||||
2,
|
||||
),
|
||||
resultDocumentTitle,
|
||||
'.json',
|
||||
ViewColumn.Beside,
|
||||
);
|
||||
} else {
|
||||
await vscodeUtil.showNewFile(JSON.stringify(response.resources, undefined, 2), resultDocumentTitle, ".json", ViewColumn.Beside);
|
||||
await vscodeUtil.showNewFile(
|
||||
JSON.stringify(response.resources, undefined, 2),
|
||||
resultDocumentTitle,
|
||||
'.json',
|
||||
ViewColumn.Beside,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { ViewColumn } from "vscode";
|
||||
import { KeyValueStore } from "../../KeyValueStore";
|
||||
import { localize } from "../../utils/localize";
|
||||
import * as vscodeUtil from "../../utils/vscodeUtils";
|
||||
import { NoSqlQueryConnection, noSqlQueryConnectionKey } from "../NoSqlCodeLensProvider";
|
||||
import { CosmosDBCredential, getCosmosClient } from "../getCosmosClient";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ViewColumn } from 'vscode';
|
||||
import { KeyValueStore } from '../../KeyValueStore';
|
||||
import { localize } from '../../utils/localize';
|
||||
import * as vscodeUtil from '../../utils/vscodeUtils';
|
||||
import { noSqlQueryConnectionKey, type NoSqlQueryConnection } from '../NoSqlCodeLensProvider';
|
||||
import { getCosmosClient, type CosmosDBCredential } from '../getCosmosClient';
|
||||
|
||||
export async function getNoSqlQueryPlan(_context: IActionContext, args: { queryText: string } | undefined): Promise<void> {
|
||||
export async function getNoSqlQueryPlan(
|
||||
_context: IActionContext,
|
||||
args: { queryText: string } | undefined,
|
||||
): Promise<void> {
|
||||
let queryText: string;
|
||||
if (!args) {
|
||||
const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
|
||||
|
@ -26,17 +29,23 @@ export async function getNoSqlQueryPlan(_context: IActionContext, args: { queryT
|
|||
}
|
||||
const connectedCollection = KeyValueStore.instance.get(noSqlQueryConnectionKey);
|
||||
if (!connectedCollection) {
|
||||
throw new Error("Unable to get query plan due to missing node data. Please connect to a Cosmos DB collection.");
|
||||
throw new Error('Unable to get query plan due to missing node data. Please connect to a Cosmos DB collection.');
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { databaseId, containerId, endpoint, masterKey, isEmulator } = connectedCollection as NoSqlQueryConnection;
|
||||
const { databaseId, containerId, endpoint, masterKey, isEmulator } =
|
||||
connectedCollection as NoSqlQueryConnection;
|
||||
const credentials: CosmosDBCredential[] = [];
|
||||
if (masterKey !== undefined) {
|
||||
credentials.push({ type: "key", key: masterKey });
|
||||
credentials.push({ type: 'key', key: masterKey });
|
||||
}
|
||||
credentials.push({ type: "auth" });
|
||||
credentials.push({ type: 'auth' });
|
||||
const client = getCosmosClient(endpoint, credentials, isEmulator);
|
||||
const response = await client.database(databaseId).container(containerId).getQueryPlan(queryText);
|
||||
await vscodeUtil.showNewFile(JSON.stringify(response.result, undefined, 2), `query results for ${containerId}`, ".json", ViewColumn.Beside);
|
||||
await vscodeUtil.showNewFile(
|
||||
JSON.stringify(response.result, undefined, 2),
|
||||
`query results for ${containerId}`,
|
||||
'.json',
|
||||
ViewColumn.Beside,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { DocDBStoredProcedureTreeItem } from "../tree/DocDBStoredProcedureTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { DocDBStoredProcedureTreeItem } from '../tree/DocDBStoredProcedureTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function openStoredProcedure(context: IActionContext, node?: DocDBStoredProcedureTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { DocDBTriggerTreeItem } from "../tree/DocDBTriggerTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { DocDBTriggerTreeItem } from '../tree/DocDBTriggerTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function openTrigger(context: IActionContext, node?: DocDBTriggerTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,18 +3,16 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { sqlFilter } from "../../constants";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { type AzExtTreeItem, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { sqlFilter } from '../../constants';
|
||||
import { ext } from '../../extensionVariables';
|
||||
|
||||
export async function pickDocDBAccount<T extends AzExtTreeItem>(
|
||||
context: IActionContext,
|
||||
expectedContextValue?: string | RegExp | (string | RegExp)[]
|
||||
expectedContextValue?: string | RegExp | (string | RegExp)[],
|
||||
): Promise<T> {
|
||||
return await ext.rgApi.pickAppResource<T>(context, {
|
||||
filter: [
|
||||
sqlFilter
|
||||
],
|
||||
expectedChildContextValue: expectedContextValue
|
||||
filter: [sqlFilter],
|
||||
expectedChildContextValue: expectedContextValue,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscodeUtil from "../../utils/vscodeUtils";
|
||||
import { DocDBCollectionTreeItem } from "../tree/DocDBCollectionTreeItem";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscodeUtil from '../../utils/vscodeUtils';
|
||||
import { DocDBCollectionTreeItem } from '../tree/DocDBCollectionTreeItem';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function viewDocDBCollectionOffer(context: IActionContext, node?: DocDBCollectionTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
@ -16,5 +16,5 @@ export async function viewDocDBCollectionOffer(context: IActionContext, node?: D
|
|||
}
|
||||
const client = node.root.getCosmosClient();
|
||||
const offer = await node.getContainerClient(client).readOffer();
|
||||
await vscodeUtil.showNewFile(JSON.stringify(offer.resource, undefined, 2), `offer of ${node.label}`, ".json");
|
||||
await vscodeUtil.showNewFile(JSON.stringify(offer.resource, undefined, 2), `offer of ${node.label}`, '.json');
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscodeUtil from "../../utils/vscodeUtils";
|
||||
import { DocDBCollectionTreeItem } from "../tree/DocDBCollectionTreeItem";
|
||||
import { setConnectedNoSqlContainer } from "./connectNoSqlContainer";
|
||||
import { pickDocDBAccount } from "./pickDocDBAccount";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscodeUtil from '../../utils/vscodeUtils';
|
||||
import { DocDBCollectionTreeItem } from '../tree/DocDBCollectionTreeItem';
|
||||
import { setConnectedNoSqlContainer } from './connectNoSqlContainer';
|
||||
import { pickDocDBAccount } from './pickDocDBAccount';
|
||||
|
||||
export async function writeNoSqlQuery(context: IActionContext, node?: DocDBCollectionTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
@ -15,5 +15,5 @@ export async function writeNoSqlQuery(context: IActionContext, node?: DocDBColle
|
|||
}
|
||||
setConnectedNoSqlContainer(node);
|
||||
const sampleQuery = `SELECT * FROM ${node.id}`;
|
||||
await vscodeUtil.showNewFile(sampleQuery, `query for ${node.label}`, ".nosql");
|
||||
await vscodeUtil.showNewFile(sampleQuery, `query for ${node.label}`, '.nosql');
|
||||
}
|
||||
|
|
|
@ -3,42 +3,48 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosClient } from "@azure/cosmos";
|
||||
import { appendExtensionUserAgent } from "@microsoft/vscode-azext-utils";
|
||||
import * as https from "https";
|
||||
import { CosmosClient } from '@azure/cosmos';
|
||||
import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils';
|
||||
import * as https from 'https';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from "../extensionVariables";
|
||||
import { ext } from '../extensionVariables';
|
||||
|
||||
// eslint-disable-next-line import/no-internal-modules
|
||||
import { getSessionFromVSCode } from "@microsoft/vscode-azext-azureauth/out/src/getSessionFromVSCode";
|
||||
import { getSessionFromVSCode } from '@microsoft/vscode-azext-azureauth/out/src/getSessionFromVSCode';
|
||||
|
||||
export type CosmosDBKeyCredential = {
|
||||
type: "key";
|
||||
type: 'key';
|
||||
key: string;
|
||||
};
|
||||
|
||||
export type CosmosDBAuthCredential = {
|
||||
type: "auth";
|
||||
type: 'auth';
|
||||
};
|
||||
|
||||
export type CosmosDBCredential = CosmosDBKeyCredential | CosmosDBAuthCredential;
|
||||
|
||||
export function getCosmosKeyCredential(credentials: CosmosDBCredential[]): CosmosDBKeyCredential | undefined {
|
||||
return credentials.filter((cred): cred is CosmosDBKeyCredential => cred.type === "key")[0];
|
||||
return credentials.filter((cred): cred is CosmosDBKeyCredential => cred.type === 'key')[0];
|
||||
}
|
||||
|
||||
export function getCosmosAuthCredential(credentials: CosmosDBCredential[]): CosmosDBAuthCredential | undefined {
|
||||
return credentials.filter((cred): cred is CosmosDBAuthCredential => cred.type === "auth")[0];
|
||||
return credentials.filter((cred): cred is CosmosDBAuthCredential => cred.type === 'auth')[0];
|
||||
}
|
||||
|
||||
export function getCosmosClient(
|
||||
endpoint: string,
|
||||
credentials: CosmosDBCredential[],
|
||||
isEmulator: boolean | undefined
|
||||
isEmulator: boolean | undefined,
|
||||
): CosmosClient {
|
||||
const vscodeStrictSSL: boolean | undefined = vscode.workspace.getConfiguration().get<boolean>(ext.settingsKeys.vsCode.proxyStrictSSL);
|
||||
const enableEndpointDiscovery: boolean | undefined = vscode.workspace.getConfiguration().get<boolean>(ext.settingsKeys.enableEndpointDiscovery);
|
||||
const connectionPolicy = { enableEndpointDiscovery: (enableEndpointDiscovery === undefined) ? true : enableEndpointDiscovery };
|
||||
const vscodeStrictSSL: boolean | undefined = vscode.workspace
|
||||
.getConfiguration()
|
||||
.get<boolean>(ext.settingsKeys.vsCode.proxyStrictSSL);
|
||||
const enableEndpointDiscovery: boolean | undefined = vscode.workspace
|
||||
.getConfiguration()
|
||||
.get<boolean>(ext.settingsKeys.enableEndpointDiscovery);
|
||||
const connectionPolicy = {
|
||||
enableEndpointDiscovery: enableEndpointDiscovery === undefined ? true : enableEndpointDiscovery,
|
||||
};
|
||||
|
||||
const keyCred = getCosmosKeyCredential(credentials);
|
||||
const authCred = getCosmosAuthCredential(credentials);
|
||||
|
@ -47,13 +53,13 @@ export function getCosmosClient(
|
|||
endpoint,
|
||||
userAgentSuffix: appendExtensionUserAgent(),
|
||||
agent: new https.Agent({ rejectUnauthorized: isEmulator ? !isEmulator : vscodeStrictSSL }),
|
||||
connectionPolicy
|
||||
connectionPolicy,
|
||||
};
|
||||
// @todo: Add telemetry to monitor usage of each credential type
|
||||
if (keyCred) {
|
||||
return new CosmosClient({
|
||||
...commonProperties,
|
||||
key: keyCred.key
|
||||
key: keyCred.key,
|
||||
});
|
||||
} else if (authCred) {
|
||||
return new CosmosClient({
|
||||
|
@ -62,13 +68,13 @@ export function getCosmosClient(
|
|||
getToken: async (scopes, _options) => {
|
||||
const session = await getSessionFromVSCode(scopes, undefined, { createIfNone: true });
|
||||
return {
|
||||
token: session?.accessToken ?? "",
|
||||
expiresOnTimestamp: 0
|
||||
token: session?.accessToken ?? '',
|
||||
expiresOnTimestamp: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
throw Error("No credential available to create CosmosClient.");
|
||||
throw Error('No credential available to create CosmosClient.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,39 +3,39 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerCommand, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils";
|
||||
import { languages } from "vscode";
|
||||
import { doubleClickDebounceDelay } from "../constants";
|
||||
import { ext } from "../extensionVariables";
|
||||
import { NoSqlCodeLensProvider } from "./NoSqlCodeLensProvider";
|
||||
import { connectNoSqlContainer } from "./commands/connectNoSqlContainer";
|
||||
import { createDocDBCollection } from "./commands/createDocDBCollection";
|
||||
import { createDocDBDatabase } from "./commands/createDocDBDatabase";
|
||||
import { createDocDBDocument } from "./commands/createDocDBDocument";
|
||||
import { createDocDBStoredProcedure } from "./commands/createDocDBStoredProcedure";
|
||||
import { createDocDBTrigger } from "./commands/createDocDBTrigger";
|
||||
import { deleteDocDBCollection } from "./commands/deleteDocDBCollection";
|
||||
import { deleteDocDBDatabase } from "./commands/deleteDocDBDatabase";
|
||||
import { deleteDocDBDocument } from "./commands/deleteDocDBDocument";
|
||||
import { deleteDocDBStoredProcedure } from "./commands/deleteDocDBStoredProcedure";
|
||||
import { deleteDocDBTrigger } from "./commands/deleteDocDBTrigger";
|
||||
import { executeDocDBStoredProcedure } from "./commands/executeDocDBStoredProcedure";
|
||||
import { executeNoSqlQuery } from "./commands/executeNoSqlQuery";
|
||||
import { getNoSqlQueryPlan } from "./commands/getNoSqlQueryPlan";
|
||||
import { openStoredProcedure } from "./commands/openStoredProcedure";
|
||||
import { openTrigger } from "./commands/openTrigger";
|
||||
import { viewDocDBCollectionOffer } from "./commands/viewDocDBCollectionOffer";
|
||||
import { writeNoSqlQuery } from "./commands/writeNoSqlQuery";
|
||||
import { registerCommand, registerCommandWithTreeNodeUnwrapping } from '@microsoft/vscode-azext-utils';
|
||||
import { languages } from 'vscode';
|
||||
import { doubleClickDebounceDelay } from '../constants';
|
||||
import { ext } from '../extensionVariables';
|
||||
import { NoSqlCodeLensProvider } from './NoSqlCodeLensProvider';
|
||||
import { connectNoSqlContainer } from './commands/connectNoSqlContainer';
|
||||
import { createDocDBCollection } from './commands/createDocDBCollection';
|
||||
import { createDocDBDatabase } from './commands/createDocDBDatabase';
|
||||
import { createDocDBDocument } from './commands/createDocDBDocument';
|
||||
import { createDocDBStoredProcedure } from './commands/createDocDBStoredProcedure';
|
||||
import { createDocDBTrigger } from './commands/createDocDBTrigger';
|
||||
import { deleteDocDBCollection } from './commands/deleteDocDBCollection';
|
||||
import { deleteDocDBDatabase } from './commands/deleteDocDBDatabase';
|
||||
import { deleteDocDBDocument } from './commands/deleteDocDBDocument';
|
||||
import { deleteDocDBStoredProcedure } from './commands/deleteDocDBStoredProcedure';
|
||||
import { deleteDocDBTrigger } from './commands/deleteDocDBTrigger';
|
||||
import { executeDocDBStoredProcedure } from './commands/executeDocDBStoredProcedure';
|
||||
import { executeNoSqlQuery } from './commands/executeNoSqlQuery';
|
||||
import { getNoSqlQueryPlan } from './commands/getNoSqlQueryPlan';
|
||||
import { openStoredProcedure } from './commands/openStoredProcedure';
|
||||
import { openTrigger } from './commands/openTrigger';
|
||||
import { viewDocDBCollectionOffer } from './commands/viewDocDBCollectionOffer';
|
||||
import { writeNoSqlQuery } from './commands/writeNoSqlQuery';
|
||||
|
||||
const nosqlLanguageId = "nosql";
|
||||
const nosqlLanguageId = 'nosql';
|
||||
|
||||
export function registerDocDBCommands(): void {
|
||||
ext.noSqlCodeLensProvider = new NoSqlCodeLensProvider();
|
||||
ext.context.subscriptions.push(languages.registerCodeLensProvider(nosqlLanguageId, ext.noSqlCodeLensProvider));
|
||||
|
||||
registerCommand("cosmosDB.connectNoSqlContainer", connectNoSqlContainer);
|
||||
registerCommand("cosmosDB.executeNoSqlQuery", executeNoSqlQuery);
|
||||
registerCommand("cosmosDB.getNoSqlQueryPlan", getNoSqlQueryPlan);
|
||||
registerCommand('cosmosDB.connectNoSqlContainer', connectNoSqlContainer);
|
||||
registerCommand('cosmosDB.executeNoSqlQuery', executeNoSqlQuery);
|
||||
registerCommand('cosmosDB.getNoSqlQueryPlan', getNoSqlQueryPlan);
|
||||
|
||||
// #region Account command
|
||||
|
||||
|
@ -54,7 +54,7 @@ export function registerDocDBCommands(): void {
|
|||
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.writeNoSqlQuery', writeNoSqlQuery);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBCollection', deleteDocDBCollection);
|
||||
registerCommandWithTreeNodeUnwrapping("cosmosDB.viewDocDBCollectionOffer", viewDocDBCollectionOffer);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.viewDocDBCollectionOffer', viewDocDBCollectionOffer);
|
||||
|
||||
// #endregion
|
||||
|
||||
|
@ -78,7 +78,11 @@ export function registerDocDBCommands(): void {
|
|||
|
||||
// #region StoredProcedure command
|
||||
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.openStoredProcedure', openStoredProcedure, doubleClickDebounceDelay);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.openStoredProcedure',
|
||||
openStoredProcedure,
|
||||
doubleClickDebounceDelay,
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteDocDBStoredProcedure', deleteDocDBStoredProcedure);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.executeDocDBStoredProcedure', executeDocDBStoredProcedure);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DatabaseDefinition, Resource } from '@azure/cosmos';
|
||||
import { type DatabaseDefinition, type Resource } from '@azure/cosmos';
|
||||
import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase';
|
||||
import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem';
|
||||
|
@ -13,7 +13,7 @@ import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem';
|
|||
import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem';
|
||||
|
||||
export class DocDBAccountTreeItem extends DocDBAccountTreeItemBase {
|
||||
public static contextValue: string = "cosmosDBDocumentServer";
|
||||
public static contextValue: string = 'cosmosDBDocumentServer';
|
||||
public contextValue: string = DocDBAccountTreeItem.contextValue;
|
||||
|
||||
public initChild(resource: DatabaseDefinition & Resource): DocDBDatabaseTreeItem {
|
||||
|
|
|
@ -3,16 +3,27 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import { CosmosClient, DatabaseDefinition, DatabaseResponse, FeedOptions, QueryIterator, Resource } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem, AzExtTreeItem, ICreateChildImplContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext';
|
||||
import { type DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import {
|
||||
type CosmosClient,
|
||||
type DatabaseDefinition,
|
||||
type DatabaseResponse,
|
||||
type FeedOptions,
|
||||
type QueryIterator,
|
||||
type Resource,
|
||||
} from '@azure/cosmos';
|
||||
import {
|
||||
type AzExtParentTreeItem,
|
||||
type AzExtTreeItem,
|
||||
type ICreateChildImplContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import type * as vscode from 'vscode';
|
||||
import { type IDeleteWizardContext } from '../../commands/deleteDatabaseAccount/IDeleteWizardContext';
|
||||
import { deleteCosmosDBAccount } from '../../commands/deleteDatabaseAccount/deleteCosmosDBAccount';
|
||||
import { getThemeAgnosticIconPath, SERVERLESS_CAPABILITY_NAME } from '../../constants';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { rejectOnTimeout } from '../../utils/timeout';
|
||||
import { CosmosDBCredential, getCosmosClient, getCosmosKeyCredential } from '../getCosmosClient';
|
||||
import { getCosmosClient, getCosmosKeyCredential, type CosmosDBCredential } from '../getCosmosClient';
|
||||
import { getSignedInPrincipalIdForAccountEndpoint } from '../utils/azureSessionHelper';
|
||||
import { ensureRbacPermission, isRbacException, showRbacPermissionError } from '../utils/rbacUtils';
|
||||
import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
||||
|
@ -23,7 +34,7 @@ import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
|||
*/
|
||||
export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<DatabaseDefinition & Resource> {
|
||||
public readonly label: string;
|
||||
public readonly childTypeLabel: string = "Database";
|
||||
public readonly childTypeLabel: string = 'Database';
|
||||
private hasShownRbacNotification: boolean = false;
|
||||
|
||||
constructor(
|
||||
|
@ -33,7 +44,7 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
endpoint: string,
|
||||
credentials: CosmosDBCredential[],
|
||||
isEmulator: boolean | undefined,
|
||||
readonly databaseAccount?: DatabaseAccountGetResults
|
||||
readonly databaseAccount?: DatabaseAccountGetResults,
|
||||
) {
|
||||
super(parent);
|
||||
this.id = id;
|
||||
|
@ -42,11 +53,11 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
endpoint,
|
||||
credentials,
|
||||
isEmulator,
|
||||
getCosmosClient: () => getCosmosClient(endpoint, credentials, isEmulator)
|
||||
getCosmosClient: () => getCosmosClient(endpoint, credentials, isEmulator),
|
||||
};
|
||||
|
||||
const keys = credentials
|
||||
.map((cred) => cred.type === "key" ? cred.key : undefined)
|
||||
.map((cred) => (cred.type === 'key' ? cred.key : undefined))
|
||||
.filter((value): value is string => value !== undefined);
|
||||
this.valuesToMask.push(id, endpoint, ...keys);
|
||||
}
|
||||
|
@ -65,8 +76,9 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
}
|
||||
|
||||
public get isServerless(): boolean {
|
||||
return this.databaseAccount?.capabilities ? this.databaseAccount.capabilities.some(cap => cap.name === SERVERLESS_CAPABILITY_NAME) : false;
|
||||
|
||||
return this.databaseAccount?.capabilities
|
||||
? this.databaseAccount.capabilities.some((cap) => cap.name === SERVERLESS_CAPABILITY_NAME)
|
||||
: false;
|
||||
}
|
||||
|
||||
public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator<DatabaseDefinition & Resource> {
|
||||
|
@ -77,7 +89,7 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
const databaseName = await context.ui.showInputBox({
|
||||
placeHolder: 'Database Name',
|
||||
validateInput: validateDatabaseName,
|
||||
stepName: 'createDatabase'
|
||||
stepName: 'createDatabase',
|
||||
});
|
||||
|
||||
const client = this.root.getCosmosClient();
|
||||
|
@ -87,17 +99,22 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
|
||||
public async loadMoreChildrenImpl(clearCache: boolean): Promise<AzExtTreeItem[]> {
|
||||
if (this.root.isEmulator) {
|
||||
const unableToReachEmulatorMessage: string = "Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again.";
|
||||
return await rejectOnTimeout(2000, () => super.loadMoreChildrenImpl(clearCache), unableToReachEmulatorMessage);
|
||||
const unableToReachEmulatorMessage: string =
|
||||
"Unable to reach emulator. Please ensure it is started and connected to the port specified by the 'cosmosDB.emulator.port' setting, then try again.";
|
||||
return await rejectOnTimeout(
|
||||
2000,
|
||||
() => super.loadMoreChildrenImpl(clearCache),
|
||||
unableToReachEmulatorMessage,
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
return await super.loadMoreChildrenImpl(clearCache);
|
||||
} catch (e) {
|
||||
if (e instanceof Error && isRbacException(e) && !this.hasShownRbacNotification) {
|
||||
this.hasShownRbacNotification = true;
|
||||
const principalId = await getSignedInPrincipalIdForAccountEndpoint(this.root.endpoint) ?? '';
|
||||
const principalId = (await getSignedInPrincipalIdForAccountEndpoint(this.root.endpoint)) ?? '';
|
||||
// chedck if the principal ID matches the one that is signed in, otherwise this might be a security problem, hence show the error message
|
||||
if (e.message.includes(`[${principalId}]`) && await ensureRbacPermission(this, principalId)) {
|
||||
if (e.message.includes(`[${principalId}]`) && (await ensureRbacPermission(this, principalId))) {
|
||||
return await super.loadMoreChildrenImpl(clearCache);
|
||||
} else {
|
||||
void showRbacPermissionError(this.fullId, principalId);
|
||||
|
@ -115,10 +132,10 @@ export abstract class DocDBAccountTreeItemBase extends DocDBTreeItemBase<Databas
|
|||
|
||||
function validateDatabaseName(name: string): string | undefined | null {
|
||||
if (!name || name.length < 1 || name.length > 255) {
|
||||
return "Name has to be between 1 and 255 chars long";
|
||||
return 'Name has to be between 1 and 255 chars long';
|
||||
}
|
||||
if (name.endsWith(" ")) {
|
||||
return "Database name cannot end with space";
|
||||
if (name.endsWith(' ')) {
|
||||
return 'Database name cannot end with space';
|
||||
}
|
||||
if (/[/\\?#=]/.test(name)) {
|
||||
return `Database name cannot contain the characters '\\', '/', '#', '?', '='`;
|
||||
|
|
|
@ -3,23 +3,35 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Container, ContainerDefinition, CosmosClient, PartitionKeyDefinition, Resource } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
type Container,
|
||||
type ContainerDefinition,
|
||||
type CosmosClient,
|
||||
type PartitionKeyDefinition,
|
||||
type Resource,
|
||||
} from '@azure/cosmos';
|
||||
import {
|
||||
AzExtParentTreeItem,
|
||||
DialogResponses,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem';
|
||||
import { type DocDBDatabaseTreeItem } from './DocDBDatabaseTreeItem';
|
||||
import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem';
|
||||
import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem';
|
||||
import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem';
|
||||
import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem';
|
||||
import { DocDBTriggerTreeItem } from './DocDBTriggerTreeItem';
|
||||
import { DocDBTriggersTreeItem } from './DocDBTriggersTreeItem';
|
||||
import { IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
import { type IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
|
||||
/**
|
||||
* Represents a DocumentDB collection
|
||||
*/
|
||||
export class DocDBCollectionTreeItem extends AzExtParentTreeItem {
|
||||
public static contextValue: string = "cosmosDBDocumentCollection";
|
||||
public static contextValue: string = 'cosmosDBDocumentCollection';
|
||||
public readonly contextValue: string = DocDBCollectionTreeItem.contextValue;
|
||||
public readonly parent: DocDBDatabaseTreeItem;
|
||||
|
||||
|
@ -27,7 +39,10 @@ export class DocDBCollectionTreeItem extends AzExtParentTreeItem {
|
|||
private readonly _storedProceduresTreeItem: DocDBStoredProceduresTreeItem;
|
||||
private readonly _triggersTreeItem: DocDBTriggersTreeItem;
|
||||
|
||||
constructor(parent: DocDBDatabaseTreeItem, private _container: ContainerDefinition & Resource) {
|
||||
constructor(
|
||||
parent: DocDBDatabaseTreeItem,
|
||||
private _container: ContainerDefinition & Resource,
|
||||
) {
|
||||
super(parent);
|
||||
this.parent = parent;
|
||||
this.documentsTreeItem = new DocDBDocumentsTreeItem(this);
|
||||
|
@ -61,7 +76,11 @@ export class DocDBCollectionTreeItem extends AzExtParentTreeItem {
|
|||
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = `Are you sure you want to delete collection '${this.label}' and its contents?`;
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteCollection' }, DialogResponses.deleteResponse);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteCollection' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await this.getContainerClient(client).delete();
|
||||
}
|
||||
|
@ -94,6 +113,6 @@ export class DocDBCollectionTreeItem extends AzExtParentTreeItem {
|
|||
}
|
||||
|
||||
public getContainerClient(client: CosmosClient): Container {
|
||||
return (this.parent.getDatabaseClient(client)).container(this.id);
|
||||
return this.parent.getDatabaseClient(client).container(this.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContainerDefinition, CosmosClient, Database, Resource } from '@azure/cosmos';
|
||||
import { type ContainerDefinition, type CosmosClient, type Database, type Resource } from '@azure/cosmos';
|
||||
import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { DocDBDatabaseTreeItemBase } from './DocDBDatabaseTreeItemBase';
|
||||
|
||||
export class DocDBDatabaseTreeItem extends DocDBDatabaseTreeItemBase {
|
||||
public static contextValue: string = "cosmosDBDocumentDatabase";
|
||||
public static contextValue: string = 'cosmosDBDocumentDatabase';
|
||||
public readonly contextValue: string = DocDBDatabaseTreeItem.contextValue;
|
||||
public readonly childTypeLabel: string = 'Collection';
|
||||
|
||||
|
|
|
@ -3,11 +3,26 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContainerDefinition, ContainerResponse, CosmosClient, DatabaseDefinition, FeedOptions, QueryIterator, RequestOptions, Resource } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, DialogResponses, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
type ContainerDefinition,
|
||||
type ContainerResponse,
|
||||
type CosmosClient,
|
||||
type DatabaseDefinition,
|
||||
type FeedOptions,
|
||||
type QueryIterator,
|
||||
type RequestOptions,
|
||||
type Resource,
|
||||
} from '@azure/cosmos';
|
||||
import {
|
||||
DialogResponses,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type ICreateChildImplContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase';
|
||||
import { type DocDBAccountTreeItemBase } from './DocDBAccountTreeItemBase';
|
||||
import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
||||
|
||||
const minThroughputFixed: number = 400;
|
||||
|
@ -60,7 +75,11 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Contai
|
|||
// Delete the database
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = `Are you sure you want to delete database '${this.label}' and its contents?`;
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDatabase' }, DialogResponses.deleteResponse);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteDatabase' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await client.database(this.id).delete();
|
||||
}
|
||||
|
@ -70,30 +89,32 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Contai
|
|||
const containerName = await context.ui.showInputBox({
|
||||
placeHolder: `Enter an id for your ${this.childTypeLabel}`,
|
||||
validateInput: validateCollectionName,
|
||||
stepName: `create${this.childTypeLabel}`
|
||||
stepName: `create${this.childTypeLabel}`,
|
||||
});
|
||||
|
||||
const containerDefinition: ContainerDefinition = {
|
||||
id: containerName
|
||||
id: containerName,
|
||||
};
|
||||
|
||||
const partitionKey = await this.getNewPartitionKey(context);
|
||||
if (partitionKey) {
|
||||
containerDefinition.partitionKey = {
|
||||
paths: [partitionKey]
|
||||
paths: [partitionKey],
|
||||
};
|
||||
}
|
||||
const options: RequestOptions = {};
|
||||
|
||||
if (!this.parent.isServerless) {
|
||||
const isFixed: boolean = !(containerDefinition.partitionKey);
|
||||
const isFixed: boolean = !containerDefinition.partitionKey;
|
||||
const minThroughput = isFixed ? minThroughputFixed : minThroughputPartitioned;
|
||||
const throughput: number = Number(await context.ui.showInputBox({
|
||||
value: minThroughput.toString(),
|
||||
prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`,
|
||||
stepName: 'throughputCapacity',
|
||||
validateInput: (input: string) => validateThroughput(isFixed, input)
|
||||
}));
|
||||
const throughput: number = Number(
|
||||
await context.ui.showInputBox({
|
||||
value: minThroughput.toString(),
|
||||
prompt: `Initial throughput capacity, between ${minThroughput} and ${maxThroughput} inclusive in increments of ${throughputStepSize}. Enter 0 if the account doesn't support throughput.`,
|
||||
stepName: 'throughputCapacity',
|
||||
validateInput: (input: string) => validateThroughput(isFixed, input),
|
||||
}),
|
||||
);
|
||||
|
||||
if (throughput !== 0) {
|
||||
options.offerThroughput = throughput;
|
||||
|
@ -102,7 +123,9 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Contai
|
|||
|
||||
context.showCreatingTreeItem(containerName);
|
||||
const client = this.root.getCosmosClient();
|
||||
const container: ContainerResponse = await client.database(this.id).containers.create(containerDefinition, options);
|
||||
const container: ContainerResponse = await client
|
||||
.database(this.id)
|
||||
.containers.create(containerDefinition, options);
|
||||
|
||||
return this.initChild(nonNullProp(container, 'resource'));
|
||||
}
|
||||
|
@ -112,7 +135,7 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Contai
|
|||
prompt: 'Enter the partition key for the collection, or leave blank for fixed size.',
|
||||
stepName: 'partitionKeyForCollection',
|
||||
validateInput: this.validatePartitionKey,
|
||||
placeHolder: 'e.g. /address/zipCode'
|
||||
placeHolder: 'e.g. /address/zipCode',
|
||||
});
|
||||
|
||||
if (partitionKey && partitionKey.length && partitionKey[0] !== '/') {
|
||||
|
@ -124,14 +147,14 @@ export abstract class DocDBDatabaseTreeItemBase extends DocDBTreeItemBase<Contai
|
|||
|
||||
protected validatePartitionKey(key: string): string | undefined {
|
||||
if (/[#?\\]/.test(key)) {
|
||||
return "Cannot contain these characters: ?,#,\\, etc.";
|
||||
return 'Cannot contain these characters: ?,#,\\, etc.';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function validateThroughput(isFixed: boolean, input: string): string | undefined | null {
|
||||
if (input === "0") {
|
||||
if (input === '0') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -141,18 +164,18 @@ function validateThroughput(isFixed: boolean, input: string): string | undefined
|
|||
if (value < minThroughput || value > maxThroughput || (value - minThroughput) % throughputStepSize !== 0) {
|
||||
return `Value must be between ${minThroughput} and ${maxThroughput} in increments of ${throughputStepSize}`;
|
||||
}
|
||||
} catch (err) {
|
||||
return "Input must be a number";
|
||||
} catch {
|
||||
return 'Input must be a number';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function validateCollectionName(name: string): string | undefined | null {
|
||||
if (!name) {
|
||||
return "Collection name cannot be empty";
|
||||
return 'Collection name cannot be empty';
|
||||
}
|
||||
if (name.endsWith(" ")) {
|
||||
return "Collection name cannot end with space";
|
||||
if (name.endsWith(' ')) {
|
||||
return 'Collection name cannot end with space';
|
||||
}
|
||||
if (/[/\\?#]/.test(name)) {
|
||||
return `Collection name cannot contain the characters '\\', '/', '#', '?'`;
|
||||
|
|
|
@ -3,16 +3,21 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosClient, Item, ItemDefinition, RequestOptions } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import { type CosmosClient, type Item, type ItemDefinition, type RequestOptions } from '@azure/cosmos';
|
||||
import {
|
||||
AzExtTreeItem,
|
||||
DialogResponses,
|
||||
type IActionContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { type IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { getDocumentTreeItemLabel } from '../../utils/vscodeUtils';
|
||||
import { DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem';
|
||||
import { type DocDBDocumentsTreeItem } from './DocDBDocumentsTreeItem';
|
||||
import { sanitizeId } from './DocDBUtils';
|
||||
import { IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
import { type IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
|
||||
const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts'];
|
||||
|
||||
|
@ -20,7 +25,7 @@ const hiddenFields: string[] = ['_rid', '_self', '_etag', '_attachments', '_ts']
|
|||
* Represents a Cosmos DB DocumentDB (SQL) document
|
||||
*/
|
||||
export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTreeItem {
|
||||
public static contextValue: string = "cosmosDBDocument";
|
||||
public static contextValue: string = 'cosmosDBDocument';
|
||||
public readonly contextValue: string = DocDBDocumentTreeItem.contextValue;
|
||||
public readonly parent: DocDBDocumentsTreeItem;
|
||||
public readonly cTime: number = Date.now();
|
||||
|
@ -30,6 +35,7 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
|
||||
constructor(parent: DocDBDocumentsTreeItem, document: ItemDefinition) {
|
||||
super(parent);
|
||||
this.parent = parent;
|
||||
this._document = document;
|
||||
this._label = getDocumentTreeItemLabel(this._document);
|
||||
ext.fileSystem.fireChangedEvent(this);
|
||||
|
@ -72,13 +78,18 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = `Are you sure you want to delete document '${this.label}'?`;
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteDocument' }, DialogResponses.deleteResponse);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteDocument' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await this.getDocumentClient(client).delete();
|
||||
}
|
||||
|
||||
public async getFileContent(): Promise<string> {
|
||||
const clonedDoc: {} = { ...this.document };
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
const clonedDoc: Object = { ...this.document };
|
||||
for (const field of hiddenFields) {
|
||||
delete clonedDoc[field];
|
||||
}
|
||||
|
@ -95,7 +106,7 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
|
||||
const client: CosmosClient = this.root.getCosmosClient();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (["_etag"].some((element) => !newData[element])) {
|
||||
if (['_etag'].some((element) => !newData[element])) {
|
||||
throw new Error(`The "_self" and "_etag" fields are required to update a document`);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
||||
|
@ -108,7 +119,8 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
|
||||
private getPartitionKeyValue(): string | number | undefined {
|
||||
const partitionKey = this.parent.parent.partitionKey;
|
||||
if (!partitionKey) { //Fixed collections -> no partitionKeyValue
|
||||
if (!partitionKey) {
|
||||
//Fixed collections -> no partitionKeyValue
|
||||
return undefined;
|
||||
}
|
||||
const fields = partitionKey.paths[0].split('/');
|
||||
|
@ -119,7 +131,8 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
for (const field of fields) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
||||
value = value ? value[field] : this.document[field];
|
||||
if (!value) { //Partition Key exists, but this document doesn't have a value
|
||||
if (!value) {
|
||||
//Partition Key exists, but this document doesn't have a value
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +141,8 @@ export class DocDBDocumentTreeItem extends AzExtTreeItem implements IEditableTre
|
|||
}
|
||||
|
||||
private getDocumentClient(client: CosmosClient): Item {
|
||||
return this.parent.getContainerClient(client).item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue());
|
||||
return this.parent
|
||||
.getContainerClient(client)
|
||||
.item(nonNullProp(this.document, 'id'), this.getPartitionKeyValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,22 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Container, CosmosClient, FeedOptions, ItemDefinition, ItemResponse, QueryIterator } from '@azure/cosmos';
|
||||
import { IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
type Container,
|
||||
type CosmosClient,
|
||||
type FeedOptions,
|
||||
type ItemDefinition,
|
||||
type ItemResponse,
|
||||
type QueryIterator,
|
||||
} from '@azure/cosmos';
|
||||
import {
|
||||
type IActionContext,
|
||||
type ICreateChildImplContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { type DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { DocDBDocumentTreeItem } from './DocDBDocumentTreeItem';
|
||||
import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
||||
|
||||
|
@ -15,9 +26,9 @@ import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
|||
* This class provides logic for DocumentDB collections
|
||||
*/
|
||||
export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
||||
public static contextValue: string = "cosmosDBDocumentsGroup";
|
||||
public static contextValue: string = 'cosmosDBDocumentsGroup';
|
||||
public readonly contextValue: string = DocDBDocumentsTreeItem.contextValue;
|
||||
public readonly childTypeLabel: string = "Documents";
|
||||
public readonly childTypeLabel: string = 'Documents';
|
||||
public readonly parent: DocDBCollectionTreeItem;
|
||||
public suppressMaskLabel = true;
|
||||
|
||||
|
@ -31,11 +42,11 @@ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
|||
}
|
||||
|
||||
public get id(): string {
|
||||
return "$Documents";
|
||||
return '$Documents';
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
return "Documents";
|
||||
return 'Documents';
|
||||
}
|
||||
|
||||
public get link(): string {
|
||||
|
@ -51,11 +62,14 @@ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
|||
}
|
||||
|
||||
public async createChildImpl(context: ICreateChildImplContext): Promise<DocDBDocumentTreeItem> {
|
||||
let docID = await context.ui.showInputBox({ prompt: "Enter a document ID or leave blank for a generated ID", stepName: 'createDocument' });
|
||||
let docID = await context.ui.showInputBox({
|
||||
prompt: 'Enter a document ID or leave blank for a generated ID',
|
||||
stepName: 'createDocument',
|
||||
});
|
||||
|
||||
docID = docID.trim();
|
||||
let body: ItemDefinition = { id: docID };
|
||||
body = (await this.promptForPartitionKey(context, body));
|
||||
body = await this.promptForPartitionKey(context, body);
|
||||
context.showCreatingTreeItem(docID);
|
||||
const item: ItemDefinition = await this.createDocument(body);
|
||||
|
||||
|
@ -63,11 +77,13 @@ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
|||
}
|
||||
|
||||
public async createDocument(body: ItemDefinition): Promise<ItemDefinition> {
|
||||
const item: ItemResponse<ItemDefinition> = await this.getContainerClient(this.root.getCosmosClient()).items.create(body);
|
||||
const item: ItemResponse<ItemDefinition> = await this.getContainerClient(
|
||||
this.root.getCosmosClient(),
|
||||
).items.create(body);
|
||||
return nonNullProp(item, 'resource');
|
||||
}
|
||||
|
||||
public documentHasPartitionKey(doc: Object): boolean {
|
||||
public documentHasPartitionKey(doc: object): boolean {
|
||||
let interim = doc;
|
||||
let partitionKey: string | undefined = this.parent.partitionKey && this.parent.partitionKey.paths[0];
|
||||
if (!partitionKey) {
|
||||
|
@ -95,7 +111,7 @@ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
|||
if (partitionKey) {
|
||||
const partitionKeyValue: string = await context.ui.showInputBox({
|
||||
prompt: `Enter a value for the partition key ("${partitionKey}")`,
|
||||
stepName: 'valueforParititionKey'
|
||||
stepName: 'valueforParititionKey',
|
||||
});
|
||||
// Unlike delete/replace, createDocument does not accept a partition key value via an options parameter.
|
||||
// We need to present the partitionKey value as part of the document contents
|
||||
|
@ -109,14 +125,14 @@ export class DocDBDocumentsTreeItem extends DocDBTreeItemBase<ItemDefinition> {
|
|||
}
|
||||
|
||||
// Create a nested Object given the partition key path and value
|
||||
private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): Object {
|
||||
private createPartitionPathObject(partitionKey: string, partitionKeyValue: string): object {
|
||||
//remove leading slash
|
||||
if (partitionKey[0] === '/') {
|
||||
partitionKey = partitionKey.slice(1);
|
||||
}
|
||||
const keyPath = partitionKey.split('/');
|
||||
const PartitionPath: Object = {};
|
||||
let interim: Object = PartitionPath;
|
||||
const PartitionPath: object = {};
|
||||
let interim: object = PartitionPath;
|
||||
let i: number;
|
||||
for (i = 0; i < keyPath.length - 1; i++) {
|
||||
interim[keyPath[i]] = {};
|
||||
|
|
|
@ -3,27 +3,37 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Resource, StoredProcedureDefinition } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath, openReadOnlyJson, randomUtils } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from "vscode";
|
||||
import { IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { type Resource, type StoredProcedureDefinition } from '@azure/cosmos';
|
||||
import {
|
||||
AzExtTreeItem,
|
||||
DialogResponses,
|
||||
openReadOnlyJson,
|
||||
randomUtils,
|
||||
type IActionContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { type IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem';
|
||||
import { IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
import { type DocDBStoredProceduresTreeItem } from './DocDBStoredProceduresTreeItem';
|
||||
import { type IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
|
||||
/**
|
||||
* Represents a Cosmos DB DocumentDB (SQL) stored procedure
|
||||
*/
|
||||
export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEditableTreeItem {
|
||||
public static contextValue: string = "cosmosDBStoredProcedure";
|
||||
public static contextValue: string = 'cosmosDBStoredProcedure';
|
||||
public readonly contextValue: string = DocDBStoredProcedureTreeItem.contextValue;
|
||||
public readonly cTime: number = Date.now();
|
||||
public readonly parent: DocDBStoredProceduresTreeItem;
|
||||
public mTime: number = Date.now();
|
||||
|
||||
constructor(parent: DocDBStoredProceduresTreeItem, public procedure: (StoredProcedureDefinition & Resource)) {
|
||||
constructor(
|
||||
parent: DocDBStoredProceduresTreeItem,
|
||||
public procedure: StoredProcedureDefinition & Resource,
|
||||
) {
|
||||
super(parent);
|
||||
ext.fileSystem.fireChangedEvent(this);
|
||||
this.commandId = 'cosmosDB.openStoredProcedure';
|
||||
|
@ -51,7 +61,6 @@ export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEdit
|
|||
|
||||
public async getFileContent(): Promise<string> {
|
||||
return typeof this.procedure.body === 'string' ? this.procedure.body : '';
|
||||
|
||||
}
|
||||
|
||||
public async refreshImpl(): Promise<void> {
|
||||
|
@ -60,7 +69,10 @@ export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEdit
|
|||
|
||||
public async writeFileContent(_context: IActionContext, content: string): Promise<void> {
|
||||
const client = this.root.getCosmosClient();
|
||||
const replace = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).replace({ id: this.id, body: content });
|
||||
const replace = await this.parent
|
||||
.getContainerClient(client)
|
||||
.scripts.storedProcedure(this.id)
|
||||
.replace({ id: this.id, body: content });
|
||||
this.procedure = nonNullProp(replace, 'resource');
|
||||
}
|
||||
|
||||
|
@ -69,20 +81,31 @@ export class DocDBStoredProcedureTreeItem extends AzExtTreeItem implements IEdit
|
|||
}
|
||||
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = localize("deleteCosmosStoredProcedure", `Are you sure you want to delete stored procedure '{0}'?`, this.label);
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteStoredProcedure' }, DialogResponses.deleteResponse);
|
||||
const message: string = localize(
|
||||
'deleteCosmosStoredProcedure',
|
||||
`Are you sure you want to delete stored procedure '{0}'?`,
|
||||
this.label,
|
||||
);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteStoredProcedure' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).delete();
|
||||
}
|
||||
|
||||
public async execute(context: IActionContext, partitionKey: string, parameters?: unknown[]): Promise<void> {
|
||||
const client = this.root.getCosmosClient();
|
||||
const result = await this.parent.getContainerClient(client).scripts.storedProcedure(this.id).execute(partitionKey, parameters);
|
||||
const result = await this.parent
|
||||
.getContainerClient(client)
|
||||
.scripts.storedProcedure(this.id)
|
||||
.execute(partitionKey, parameters);
|
||||
|
||||
try {
|
||||
const resultFileName = `${this.label}-result`;
|
||||
await openReadOnlyJson({ label: resultFileName, fullId: randomUtils.getRandomHexString() }, result);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
await context.ui.showWarningMessage(`Unable to parse execution result`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,21 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, StoredProcedureDefinition } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from "vscode";
|
||||
import {
|
||||
type Container,
|
||||
type CosmosClient,
|
||||
type FeedOptions,
|
||||
type QueryIterator,
|
||||
type Resource,
|
||||
type StoredProcedureDefinition,
|
||||
} from '@azure/cosmos';
|
||||
import { type AzExtTreeItem, type ICreateChildImplContext, type TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { defaultStoredProcedure } from '../../constants';
|
||||
import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem';
|
||||
import { type GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { type DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { DocDBStoredProcedureTreeItem } from './DocDBStoredProcedureTreeItem';
|
||||
import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
||||
|
||||
|
@ -18,9 +25,9 @@ import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
|||
* This class represents the DocumentDB "Stored Procedures" node in the tree
|
||||
*/
|
||||
export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase<StoredProcedureDefinition> {
|
||||
public static contextValue: string = "cosmosDBStoredProceduresGroup";
|
||||
public static contextValue: string = 'cosmosDBStoredProceduresGroup';
|
||||
public readonly contextValue: string = DocDBStoredProceduresTreeItem.contextValue;
|
||||
public readonly childTypeLabel: string = "Stored Procedure";
|
||||
public readonly childTypeLabel: string = 'Stored Procedure';
|
||||
public readonly parent: DocDBCollectionTreeItem | GraphCollectionTreeItem;
|
||||
public suppressMaskLabel = true;
|
||||
|
||||
|
@ -42,13 +49,15 @@ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase<StoredProce
|
|||
const currStoredProcedureList: AzExtTreeItem[] = await this.getCachedChildren(context);
|
||||
const currStoredProcedureNames: string[] = [];
|
||||
for (const sp of currStoredProcedureList) {
|
||||
currStoredProcedureNames.push(nonNullProp(sp, "id"));
|
||||
currStoredProcedureNames.push(nonNullProp(sp, 'id'));
|
||||
}
|
||||
const spID = (await context.ui.showInputBox({
|
||||
prompt: "Enter a unique stored procedure ID",
|
||||
stepName: 'createStoredProcedure',
|
||||
validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames)
|
||||
})).trim();
|
||||
const spID = (
|
||||
await context.ui.showInputBox({
|
||||
prompt: 'Enter a unique stored procedure ID',
|
||||
stepName: 'createStoredProcedure',
|
||||
validateInput: (name: string) => this.validateStoredProcedureName(name, currStoredProcedureNames),
|
||||
})
|
||||
).trim();
|
||||
const body: StoredProcedureDefinition = { id: spID, body: defaultStoredProcedure };
|
||||
context.showCreatingTreeItem(spID);
|
||||
const sproc = await this.getContainerClient(client).scripts.storedProcedures.create(body);
|
||||
|
@ -57,18 +66,21 @@ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase<StoredProce
|
|||
}
|
||||
|
||||
public get id(): string {
|
||||
return "$StoredProcedures";
|
||||
return '$StoredProcedures';
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
return "Stored Procedures";
|
||||
return 'Stored Procedures';
|
||||
}
|
||||
|
||||
public get link(): string {
|
||||
return this.parent.link;
|
||||
}
|
||||
|
||||
public getIterator(client: CosmosClient, feedOptions: FeedOptions): QueryIterator<StoredProcedureDefinition & Resource> {
|
||||
public getIterator(
|
||||
client: CosmosClient,
|
||||
feedOptions: FeedOptions,
|
||||
): QueryIterator<StoredProcedureDefinition & Resource> {
|
||||
return this.getContainerClient(client).scripts.storedProcedures.readAll(feedOptions);
|
||||
}
|
||||
|
||||
|
@ -78,14 +90,14 @@ export class DocDBStoredProceduresTreeItem extends DocDBTreeItemBase<StoredProce
|
|||
|
||||
private validateStoredProcedureName(name: string, currStoredProcedureNames: string[]): string | undefined {
|
||||
if (name.length < 1 || name.length > 255) {
|
||||
return localize("nameLength", "Name has to be between 1 and 255 chars long");
|
||||
return localize('nameLength', 'Name has to be between 1 and 255 chars long');
|
||||
}
|
||||
|
||||
if (/[/\\?#&]/.test(name)) {
|
||||
return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &");
|
||||
return localize('illegalChars', 'Name contains illegal chars: /, \\, ?, #, &');
|
||||
}
|
||||
if (name[name.length - 1] === " ") {
|
||||
return localize("endsWithSpace", "Name cannot end with a space.");
|
||||
if (name[name.length - 1] === ' ') {
|
||||
return localize('endsWithSpace', 'Name cannot end with a space.');
|
||||
}
|
||||
if (currStoredProcedureNames.includes(name)) {
|
||||
return localize('nameExists', 'Stored Procedure "{0}" already exists.', name);
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosClient, FeedOptions, QueryIterator } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem, AzExtTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import { type CosmosClient, type FeedOptions, type QueryIterator } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem, type AzExtTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import { getBatchSizeSetting } from '../../utils/workspacUtils';
|
||||
import { IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
import { type IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
|
||||
/**
|
||||
* This class provides common iteration logic for DocumentDB accounts, databases, and collections
|
||||
|
|
|
@ -3,28 +3,33 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Resource, TriggerDefinition } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from "vscode";
|
||||
import { IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { type Resource, type TriggerDefinition } from '@azure/cosmos';
|
||||
import {
|
||||
AzExtTreeItem,
|
||||
DialogResponses,
|
||||
type IActionContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { type IEditableTreeItem } from '../../DatabasesFileSystem';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBTriggersTreeItem, getTriggerOperation, getTriggerType } from './DocDBTriggersTreeItem';
|
||||
import { IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
import { getTriggerOperation, getTriggerType, type DocDBTriggersTreeItem } from './DocDBTriggersTreeItem';
|
||||
import { type IDocDBTreeRoot } from './IDocDBTreeRoot';
|
||||
|
||||
/**
|
||||
* Represents a Cosmos DB DocumentDB (SQL) trigger
|
||||
*/
|
||||
export class DocDBTriggerTreeItem extends AzExtTreeItem implements IEditableTreeItem {
|
||||
public static contextValue: string = "cosmosDBTrigger";
|
||||
public static contextValue: string = 'cosmosDBTrigger';
|
||||
public readonly contextValue: string = DocDBTriggerTreeItem.contextValue;
|
||||
public readonly cTime: number = Date.now();
|
||||
public readonly parent: DocDBTriggersTreeItem;
|
||||
public trigger: (TriggerDefinition & Resource);
|
||||
public trigger: TriggerDefinition & Resource;
|
||||
public mTime: number = Date.now();
|
||||
|
||||
constructor(parent: DocDBTriggersTreeItem, trigger: (TriggerDefinition & Resource)) {
|
||||
constructor(parent: DocDBTriggersTreeItem, trigger: TriggerDefinition & Resource) {
|
||||
super(parent);
|
||||
this.trigger = trigger;
|
||||
ext.fileSystem.fireChangedEvent(this);
|
||||
|
@ -77,7 +82,7 @@ export class DocDBTriggerTreeItem extends AzExtTreeItem implements IEditableTree
|
|||
id: this.id,
|
||||
triggerType: triggerType,
|
||||
triggerOperation: triggerOperation,
|
||||
body: content
|
||||
body: content,
|
||||
});
|
||||
this.trigger = nonNullProp(replace, 'resource');
|
||||
}
|
||||
|
@ -87,8 +92,16 @@ export class DocDBTriggerTreeItem extends AzExtTreeItem implements IEditableTree
|
|||
}
|
||||
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = localize("deleteCosmosTrigger", `Are you sure you want to delete trigger '{0}'?`, this.label);
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteTrigger' }, DialogResponses.deleteResponse);
|
||||
const message: string = localize(
|
||||
'deleteCosmosTrigger',
|
||||
`Are you sure you want to delete trigger '{0}'?`,
|
||||
this.label,
|
||||
);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteTrigger' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await this.parent.getContainerClient(client).scripts.trigger(this.id).delete();
|
||||
}
|
||||
|
|
|
@ -3,14 +3,28 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Container, CosmosClient, FeedOptions, QueryIterator, Resource, TriggerDefinition, TriggerOperation, TriggerType } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, IActionContext, ICreateChildImplContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from "vscode";
|
||||
import {
|
||||
TriggerOperation,
|
||||
TriggerType,
|
||||
type Container,
|
||||
type CosmosClient,
|
||||
type FeedOptions,
|
||||
type QueryIterator,
|
||||
type Resource,
|
||||
type TriggerDefinition,
|
||||
} from '@azure/cosmos';
|
||||
import {
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type ICreateChildImplContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { defaultTrigger } from '../../constants';
|
||||
import { GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem';
|
||||
import { type GraphCollectionTreeItem } from '../../graph/tree/GraphCollectionTreeItem';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { nonNullProp } from '../../utils/nonNull';
|
||||
import { DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { type DocDBCollectionTreeItem } from './DocDBCollectionTreeItem';
|
||||
import { DocDBTreeItemBase } from './DocDBTreeItemBase';
|
||||
import { DocDBTriggerTreeItem } from './DocDBTriggerTreeItem';
|
||||
|
||||
|
@ -18,10 +32,9 @@ import { DocDBTriggerTreeItem } from './DocDBTriggerTreeItem';
|
|||
* This class represents the DocumentDB "Triggers" node in the tree
|
||||
*/
|
||||
export class DocDBTriggersTreeItem extends DocDBTreeItemBase<TriggerDefinition> {
|
||||
|
||||
public static contextValue: string = "cosmosDBTriggersGroup";
|
||||
public static contextValue: string = 'cosmosDBTriggersGroup';
|
||||
public readonly contextValue: string = DocDBTriggersTreeItem.contextValue;
|
||||
public readonly childTypeLabel: string = "Trigger";
|
||||
public readonly childTypeLabel: string = 'Trigger';
|
||||
public readonly parent: DocDBCollectionTreeItem;
|
||||
public suppressMaskLabel = true;
|
||||
|
||||
|
@ -43,19 +56,26 @@ export class DocDBTriggersTreeItem extends DocDBTreeItemBase<TriggerDefinition>
|
|||
const currTriggerList: AzExtTreeItem[] = await this.getCachedChildren(context);
|
||||
const currTriggerNames: string[] = [];
|
||||
for (const sp of currTriggerList) {
|
||||
currTriggerNames.push(nonNullProp(sp, "id"));
|
||||
currTriggerNames.push(nonNullProp(sp, 'id'));
|
||||
}
|
||||
|
||||
const triggerID = (await context.ui.showInputBox({
|
||||
prompt: "Enter a unique trigger ID",
|
||||
stepName: 'createTrigger',
|
||||
validateInput: (name: string) => this.validateTriggerName(name, currTriggerNames)
|
||||
})).trim();
|
||||
const triggerID = (
|
||||
await context.ui.showInputBox({
|
||||
prompt: 'Enter a unique trigger ID',
|
||||
stepName: 'createTrigger',
|
||||
validateInput: (name: string) => this.validateTriggerName(name, currTriggerNames),
|
||||
})
|
||||
).trim();
|
||||
|
||||
const triggerType = await getTriggerType(context);
|
||||
const triggerOperation = await getTriggerOperation(context);
|
||||
|
||||
const body: TriggerDefinition = { id: triggerID, body: defaultTrigger, triggerType: triggerType, triggerOperation: triggerOperation };
|
||||
const body: TriggerDefinition = {
|
||||
id: triggerID,
|
||||
body: defaultTrigger,
|
||||
triggerType: triggerType,
|
||||
triggerOperation: triggerOperation,
|
||||
};
|
||||
context.showCreatingTreeItem(triggerID);
|
||||
const response = await this.getContainerClient(client).scripts.triggers.create(body);
|
||||
|
||||
|
@ -63,11 +83,11 @@ export class DocDBTriggersTreeItem extends DocDBTreeItemBase<TriggerDefinition>
|
|||
}
|
||||
|
||||
public get id(): string {
|
||||
return "$Triggers";
|
||||
return '$Triggers';
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
return "Triggers";
|
||||
return 'Triggers';
|
||||
}
|
||||
|
||||
public get link(): string {
|
||||
|
@ -84,14 +104,14 @@ export class DocDBTriggersTreeItem extends DocDBTreeItemBase<TriggerDefinition>
|
|||
|
||||
private validateTriggerName(name: string, currTriggerNames: string[]): string | undefined {
|
||||
if (name.length < 1 || name.length > 255) {
|
||||
return localize("nameLength", "Name has to be between 1 and 255 chars long");
|
||||
return localize('nameLength', 'Name has to be between 1 and 255 chars long');
|
||||
}
|
||||
|
||||
if (/[/\\?#&]/.test(name)) {
|
||||
return localize("illegalChars", "Name contains illegal chars: /, \\, ?, #, &");
|
||||
return localize('illegalChars', 'Name contains illegal chars: /, \\, ?, #, &');
|
||||
}
|
||||
if (name[name.length - 1] === " ") {
|
||||
return localize("endsWithSpace", "Name cannot end with a space.");
|
||||
if (name[name.length - 1] === ' ') {
|
||||
return localize('endsWithSpace', 'Name cannot end with a space.');
|
||||
}
|
||||
if (currTriggerNames.includes(name)) {
|
||||
return localize('nameExists', 'Trigger "{0}" already exists.', name);
|
||||
|
@ -104,15 +124,15 @@ export class DocDBTriggersTreeItem extends DocDBTreeItemBase<TriggerDefinition>
|
|||
export async function getTriggerType(context: IActionContext): Promise<TriggerType> {
|
||||
const options = Object.keys(TriggerType).map((type) => ({ label: type }));
|
||||
const triggerTypeOption = await context.ui.showQuickPick<vscode.QuickPickItem>(options, {
|
||||
placeHolder: localize("createDocDBTriggerSelectType", "Select the trigger type")
|
||||
placeHolder: localize('createDocDBTriggerSelectType', 'Select the trigger type'),
|
||||
});
|
||||
return triggerTypeOption.label === "Pre" ? TriggerType.Pre : TriggerType.Post;
|
||||
return triggerTypeOption.label === 'Pre' ? TriggerType.Pre : TriggerType.Post;
|
||||
}
|
||||
|
||||
export async function getTriggerOperation(context: IActionContext): Promise<TriggerOperation> {
|
||||
const options = Object.keys(TriggerOperation).map((key) => ({ label: key }));
|
||||
const triggerOperationOption = await context.ui.showQuickPick<vscode.QuickPickItem>(options, {
|
||||
placeHolder: localize("createDocDBTriggerSelectOperation", "Select the trigger operation")
|
||||
placeHolder: localize('createDocDBTriggerSelectOperation', 'Select the trigger operation'),
|
||||
});
|
||||
return TriggerOperation[triggerOperationOption.label as keyof typeof TriggerOperation];
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosClient } from "@azure/cosmos";
|
||||
import { CosmosDBCredential } from "../getCosmosClient";
|
||||
import { type CosmosClient } from '@azure/cosmos';
|
||||
import { type CosmosDBCredential } from '../getCosmosClient';
|
||||
|
||||
export interface IDocDBTreeRoot {
|
||||
endpoint: string;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// eslint-disable-next-line import/no-internal-modules
|
||||
import { getSessionFromVSCode } from '@microsoft/vscode-azext-azureauth/out/src/getSessionFromVSCode';
|
||||
import * as vscode from "vscode";
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export async function getSignedInPrincipalIdForAccountEndpoint(accountEndpoint: string): Promise<string | undefined> {
|
||||
const session = await getSessionForDatabaseAccount(accountEndpoint);
|
||||
|
|
|
@ -3,72 +3,114 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SqlRoleAssignmentCreateUpdateParameters } from '@azure/arm-cosmosdb';
|
||||
import { type SqlRoleAssignmentCreateUpdateParameters } from '@azure/arm-cosmosdb';
|
||||
import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils';
|
||||
import { callWithTelemetryAndErrorHandling, IActionContext, IAzureMessageOptions, ISubscriptionContext } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
type IActionContext,
|
||||
type IAzureMessageOptions,
|
||||
type ISubscriptionContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { randomUUID } from 'crypto';
|
||||
import * as vscode from 'vscode';
|
||||
import { createCosmosDBClient } from '../../utils/azureClients';
|
||||
import { getDatabaseAccountNameFromId } from '../../utils/azureUtils';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { DocDBAccountTreeItemBase } from '../tree/DocDBAccountTreeItemBase';
|
||||
import { type DocDBAccountTreeItemBase } from '../tree/DocDBAccountTreeItemBase';
|
||||
|
||||
export async function ensureRbacPermission(docDbItem: DocDBAccountTreeItemBase, principalId: string): Promise<boolean> {
|
||||
return await callWithTelemetryAndErrorHandling('cosmosDB.addMissingRbacRole', async (context: IActionContext) => {
|
||||
return (
|
||||
(await callWithTelemetryAndErrorHandling('cosmosDB.addMissingRbacRole', async (context: IActionContext) => {
|
||||
context.errorHandling.suppressDisplay = false;
|
||||
context.errorHandling.rethrow = false;
|
||||
|
||||
context.errorHandling.suppressDisplay = false;
|
||||
context.errorHandling.rethrow = false;
|
||||
const accountName: string = getDatabaseAccountNameFromId(docDbItem.fullId);
|
||||
if (await askForRbacPermissions(accountName, docDbItem.subscription.subscriptionDisplayName, context)) {
|
||||
context.telemetry.properties.lastStep = 'addRbacContributorPermission';
|
||||
const resourceGroup: string = getResourceGroupFromId(docDbItem.fullId);
|
||||
const start: number = Date.now();
|
||||
await addRbacContributorPermission(
|
||||
accountName,
|
||||
principalId,
|
||||
resourceGroup,
|
||||
context,
|
||||
docDbItem.subscription,
|
||||
);
|
||||
//send duration of the previous call (in seconds) in addition to the duration of the whole event including user prompt
|
||||
context.telemetry.measurements['createRoleAssignment'] = (Date.now() - start) / 1000;
|
||||
|
||||
const accountName: string = getDatabaseAccountNameFromId(docDbItem.fullId);
|
||||
if (await askForRbacPermissions(accountName, docDbItem.subscription.subscriptionDisplayName, context)) {
|
||||
context.telemetry.properties.lastStep = "addRbacContributorPermission";
|
||||
const resourceGroup: string = getResourceGroupFromId(docDbItem.fullId);
|
||||
const start: number = Date.now();
|
||||
await addRbacContributorPermission(accountName, principalId, resourceGroup, context, docDbItem.subscription);
|
||||
//send duration of the previous call (in seconds) in addition to the duration of the whole event including user prompt
|
||||
context.telemetry.measurements["createRoleAssignment"] = (Date.now() - start) / 1000;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}) ?? false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})) ?? false
|
||||
);
|
||||
}
|
||||
|
||||
export function isRbacException(error: Error): boolean {
|
||||
return (error instanceof Error && error.message.includes("does not have required RBAC permissions to perform action"));
|
||||
return (
|
||||
error instanceof Error && error.message.includes('does not have required RBAC permissions to perform action')
|
||||
);
|
||||
}
|
||||
|
||||
export async function showRbacPermissionError(accountName: string, principalId: string): Promise<void> {
|
||||
const message = localize("rbacPermissionErrorMsg", "You do not have the required permissions to access [{0}] with your principal Id [{1}].\nPlease contact the account owner to get the required permissions.", accountName, principalId);
|
||||
const readMoreItem = localize("learnMore", "Learn More");
|
||||
const message = localize(
|
||||
'rbacPermissionErrorMsg',
|
||||
'You do not have the required permissions to access [{0}] with your principal Id [{1}].\nPlease contact the account owner to get the required permissions.',
|
||||
accountName,
|
||||
principalId,
|
||||
);
|
||||
const readMoreItem = localize('learnMore', 'Learn More');
|
||||
await vscode.window.showErrorMessage(message, { modal: false }, ...[readMoreItem]).then((item) => {
|
||||
if (item === readMoreItem) {
|
||||
void vscode.env.openExternal(vscode.Uri.parse("https://aka.ms/cosmos-native-rbac"));
|
||||
void vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/cosmos-native-rbac'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function askForRbacPermissions(databaseAccount: string, subscription: string, context: IActionContext): Promise<boolean> {
|
||||
const message =
|
||||
[localize("rbacMissingErrorMsg", "You need the 'Data Contributor' RBAC role permission to enable all Azure Databases Extension features for the selected account.\n\n"),
|
||||
localize("rbacMissingErrorAccountName", "Account Name: {0}\n", databaseAccount),
|
||||
localize("rbacMissingErrorSubscriptionName", "Subscription: {0}\n", subscription)
|
||||
].join("");
|
||||
const options: IAzureMessageOptions = { modal: true, detail: message, learnMoreLink: "https://aka.ms/cosmos-native-rbac", stepName: "askSetRbac" };
|
||||
const setPermissionItem: vscode.MessageItem = { title: localize("rbacExtendPermissionBtn", "Extend RBAC permissions") };
|
||||
async function askForRbacPermissions(
|
||||
databaseAccount: string,
|
||||
subscription: string,
|
||||
context: IActionContext,
|
||||
): Promise<boolean> {
|
||||
const message = [
|
||||
localize(
|
||||
'rbacMissingErrorMsg',
|
||||
"You need the 'Data Contributor' RBAC role permission to enable all Azure Databases Extension features for the selected account.\n\n",
|
||||
),
|
||||
localize('rbacMissingErrorAccountName', 'Account Name: {0}\n', databaseAccount),
|
||||
localize('rbacMissingErrorSubscriptionName', 'Subscription: {0}\n', subscription),
|
||||
].join('');
|
||||
const options: IAzureMessageOptions = {
|
||||
modal: true,
|
||||
detail: message,
|
||||
learnMoreLink: 'https://aka.ms/cosmos-native-rbac',
|
||||
stepName: 'askSetRbac',
|
||||
};
|
||||
const setPermissionItem: vscode.MessageItem = {
|
||||
title: localize('rbacExtendPermissionBtn', 'Extend RBAC permissions'),
|
||||
};
|
||||
|
||||
const result = await context.ui.showWarningMessage(localize("rbacMissingErrorTitle", "No required RBAC permissions"), options, ...[setPermissionItem]);
|
||||
const result = await context.ui.showWarningMessage(
|
||||
localize('rbacMissingErrorTitle', 'No required RBAC permissions'),
|
||||
options,
|
||||
...[setPermissionItem],
|
||||
);
|
||||
return result === setPermissionItem;
|
||||
}
|
||||
|
||||
async function addRbacContributorPermission(databaseAccount: string, principalId: string, resourceGroup: string, context: IActionContext, subscription: ISubscriptionContext): Promise<string | undefined> {
|
||||
const defaultRoleId = "00000000-0000-0000-0000-000000000002"; // this is a predefined role with read and write access to data plane resources
|
||||
async function addRbacContributorPermission(
|
||||
databaseAccount: string,
|
||||
principalId: string,
|
||||
resourceGroup: string,
|
||||
context: IActionContext,
|
||||
subscription: ISubscriptionContext,
|
||||
): Promise<string | undefined> {
|
||||
const defaultRoleId = '00000000-0000-0000-0000-000000000002'; // this is a predefined role with read and write access to data plane resources
|
||||
const fullAccountId = `/subscriptions/${subscription.subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${databaseAccount}`;
|
||||
|
||||
const createUpdateSqlRoleAssignmentParameters: SqlRoleAssignmentCreateUpdateParameters =
|
||||
{
|
||||
const createUpdateSqlRoleAssignmentParameters: SqlRoleAssignmentCreateUpdateParameters = {
|
||||
principalId: principalId,
|
||||
roleDefinitionId: fullAccountId + "/sqlRoleDefinitions/" + defaultRoleId,
|
||||
roleDefinitionId: fullAccountId + '/sqlRoleDefinitions/' + defaultRoleId,
|
||||
scope: fullAccountId,
|
||||
};
|
||||
|
||||
|
@ -82,8 +124,12 @@ async function addRbacContributorPermission(databaseAccount: string, principalId
|
|||
|
||||
const roleAssignmentId = randomUUID();
|
||||
const client = await createCosmosDBClient([context, subscription]);
|
||||
const create = await client.sqlResources.beginCreateUpdateSqlRoleAssignmentAndWait(roleAssignmentId, resourceGroup, databaseAccount, createUpdateSqlRoleAssignmentParameters);
|
||||
const create = await client.sqlResources.beginCreateUpdateSqlRoleAssignmentAndWait(
|
||||
roleAssignmentId,
|
||||
resourceGroup,
|
||||
databaseAccount,
|
||||
createUpdateSqlRoleAssignmentParameters,
|
||||
);
|
||||
|
||||
return create.id;
|
||||
}
|
||||
|
||||
|
|
256
src/extension.ts
256
src/extension.ts
|
@ -6,7 +6,22 @@
|
|||
'use strict';
|
||||
|
||||
import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils';
|
||||
import { AzExtParentTreeItem, AzExtTreeItem, AzureExtensionApi, IActionContext, ITreeItemPickerContext, apiUtils, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtLogOutputChannel, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
createApiProvider,
|
||||
createAzExtLogOutputChannel,
|
||||
registerCommandWithTreeNodeUnwrapping,
|
||||
registerErrorHandler,
|
||||
registerEvent,
|
||||
registerReportIssueCommand,
|
||||
registerUIExtensionVariables,
|
||||
type AzExtParentTreeItem,
|
||||
type AzExtTreeItem,
|
||||
type AzureExtensionApi,
|
||||
type IActionContext,
|
||||
type ITreeItemPickerContext,
|
||||
type apiUtils,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { AzExtResourceType } from '@microsoft/vscode-azureresources-api';
|
||||
import { platform } from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
|
@ -16,11 +31,17 @@ import { pickTreeItem } from './commands/api/pickTreeItem';
|
|||
import { revealTreeItem } from './commands/api/revealTreeItem';
|
||||
import { deleteDatabaseAccount } from './commands/deleteDatabaseAccount/deleteDatabaseAccount';
|
||||
import { importDocuments } from './commands/importDocuments';
|
||||
import { cosmosGremlinFilter, cosmosMongoFilter, cosmosTableFilter, doubleClickDebounceDelay, sqlFilter } from './constants';
|
||||
import {
|
||||
cosmosGremlinFilter,
|
||||
cosmosMongoFilter,
|
||||
cosmosTableFilter,
|
||||
doubleClickDebounceDelay,
|
||||
sqlFilter,
|
||||
} from './constants';
|
||||
import { registerDocDBCommands } from './docdb/registerDocDBCommands';
|
||||
import { DocDBAccountTreeItem } from './docdb/tree/DocDBAccountTreeItem';
|
||||
import { DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem';
|
||||
import { type DocDBAccountTreeItemBase } from './docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { type DocDBCollectionTreeItem } from './docdb/tree/DocDBCollectionTreeItem';
|
||||
import { DocDBDocumentTreeItem } from './docdb/tree/DocDBDocumentTreeItem';
|
||||
import { ext } from './extensionVariables';
|
||||
import { getResourceGroupsApi } from './getExtensionApi';
|
||||
|
@ -29,7 +50,7 @@ import { GraphAccountTreeItem } from './graph/tree/GraphAccountTreeItem';
|
|||
import { registerMongoCommands } from './mongo/registerMongoCommands';
|
||||
import { setConnectedNode } from './mongo/setConnectedNode';
|
||||
import { MongoAccountTreeItem } from './mongo/tree/MongoAccountTreeItem';
|
||||
import { MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem';
|
||||
import { type MongoCollectionTreeItem } from './mongo/tree/MongoCollectionTreeItem';
|
||||
import { MongoDocumentTreeItem } from './mongo/tree/MongoDocumentTreeItem';
|
||||
import { registerPostgresCommands } from './postgres/commands/registerPostgresCommands';
|
||||
import { DatabaseResolver } from './resolver/AppResolver';
|
||||
|
@ -39,13 +60,22 @@ import { AttachedAccountSuffix } from './tree/AttachedAccountsTreeItem';
|
|||
import { SubscriptionTreeItem } from './tree/SubscriptionTreeItem';
|
||||
import { localize } from './utils/localize';
|
||||
|
||||
const cosmosDBTopLevelContextValues: string[] = [GraphAccountTreeItem.contextValue, DocDBAccountTreeItem.contextValue, TableAccountTreeItem.contextValue, MongoAccountTreeItem.contextValue];
|
||||
const cosmosDBTopLevelContextValues: string[] = [
|
||||
GraphAccountTreeItem.contextValue,
|
||||
DocDBAccountTreeItem.contextValue,
|
||||
TableAccountTreeItem.contextValue,
|
||||
MongoAccountTreeItem.contextValue,
|
||||
];
|
||||
|
||||
export async function activateInternal(context: vscode.ExtensionContext, perfStats: { loadStartTime: number, loadEndTime: number }, ignoreBundle?: boolean): Promise<apiUtils.AzureExtensionApiProvider> {
|
||||
export async function activateInternal(
|
||||
context: vscode.ExtensionContext,
|
||||
perfStats: { loadStartTime: number; loadEndTime: number },
|
||||
ignoreBundle?: boolean,
|
||||
): Promise<apiUtils.AzureExtensionApiProvider> {
|
||||
ext.context = context;
|
||||
ext.ignoreBundle = ignoreBundle;
|
||||
|
||||
ext.outputChannel = createAzExtLogOutputChannel("Azure Databases");
|
||||
ext.outputChannel = createAzExtLogOutputChannel('Azure Databases');
|
||||
context.subscriptions.push(ext.outputChannel);
|
||||
registerUIExtensionVariables(ext);
|
||||
registerAzureUtilsExtensionVariables(ext);
|
||||
|
@ -58,10 +88,18 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
|
|||
|
||||
ext.rgApi = await getResourceGroupsApi();
|
||||
ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.AzureCosmosDb, new DatabaseResolver());
|
||||
ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersStandard, new DatabaseResolver());
|
||||
ext.rgApi.registerApplicationResourceResolver(AzExtResourceType.PostgresqlServersFlexible, new DatabaseResolver());
|
||||
ext.rgApi.registerApplicationResourceResolver(
|
||||
AzExtResourceType.PostgresqlServersStandard,
|
||||
new DatabaseResolver(),
|
||||
);
|
||||
ext.rgApi.registerApplicationResourceResolver(
|
||||
AzExtResourceType.PostgresqlServersFlexible,
|
||||
new DatabaseResolver(),
|
||||
);
|
||||
|
||||
const workspaceRootTreeItem = (ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem })._rootTreeItem;
|
||||
const workspaceRootTreeItem = (
|
||||
ext.rgApi.workspaceResourceTree as unknown as { _rootTreeItem: AzExtParentTreeItem }
|
||||
)._rootTreeItem;
|
||||
const databaseWorkspaceProvider = new DatabaseWorkspaceProvider(workspaceRootTreeItem);
|
||||
ext.rgApi.registerWorkspaceResourceProvider('AttachedDatabaseAccount', databaseWorkspaceProvider);
|
||||
|
||||
|
@ -72,99 +110,141 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
|
|||
registerPostgresCommands();
|
||||
registerMongoCommands();
|
||||
|
||||
context.subscriptions.push(vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem));
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.registerFileSystemProvider(DatabasesFileSystem.scheme, ext.fileSystem),
|
||||
);
|
||||
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () => vscode.commands.executeCommand("azure-account.selectSubscriptions"));
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.selectSubscriptions', () =>
|
||||
vscode.commands.executeCommand('azure-account.selectSubscriptions'),
|
||||
);
|
||||
|
||||
registerCommandWithTreeNodeUnwrapping('azureDatabases.createServer', createServer);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteAccount', deleteAccount);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.attachDatabaseAccount', async (actionContext: IActionContext) => {
|
||||
await ext.attachedAccountsNode.attachNewAccount(actionContext);
|
||||
await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode);
|
||||
});
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.attachDatabaseAccount',
|
||||
async (actionContext: IActionContext) => {
|
||||
await ext.attachedAccountsNode.attachNewAccount(actionContext);
|
||||
await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode);
|
||||
},
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.attachEmulator', async (actionContext: IActionContext) => {
|
||||
if (platform() !== 'win32') {
|
||||
actionContext.errorHandling.suppressReportIssue = true;
|
||||
throw new Error(localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.'));
|
||||
throw new Error(
|
||||
localize('emulatorNotSupported', 'The Cosmos DB emulator is only supported on Windows.'),
|
||||
);
|
||||
}
|
||||
|
||||
await ext.attachedAccountsNode.attachEmulator(actionContext);
|
||||
await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode);
|
||||
});
|
||||
registerCommandWithTreeNodeUnwrapping('azureDatabases.refresh', async (actionContext: IActionContext, node?: AzExtTreeItem) => {
|
||||
if (node) {
|
||||
await node.refresh(actionContext);
|
||||
} else {
|
||||
await ext.rgApi.appResourceTree.refresh(actionContext, node);
|
||||
}
|
||||
});
|
||||
|
||||
registerCommandWithTreeNodeUnwrapping('azureDatabases.detachDatabaseAccount', async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => {
|
||||
const children = await ext.attachedAccountsNode.loadAllChildren(actionContext);
|
||||
if (children[0].contextValue === "cosmosDBAttachDatabaseAccount") {
|
||||
const message = localize('noAttachedAccounts', 'There are no Attached Accounts.');
|
||||
void vscode.window.showInformationMessage(message);
|
||||
} else {
|
||||
if (!node) {
|
||||
node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker<AzExtTreeItem>(cosmosDBTopLevelContextValues.map((val: string) => val += AttachedAccountSuffix), actionContext);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'azureDatabases.refresh',
|
||||
async (actionContext: IActionContext, node?: AzExtTreeItem) => {
|
||||
if (node) {
|
||||
await node.refresh(actionContext);
|
||||
} else {
|
||||
await ext.rgApi.appResourceTree.refresh(actionContext, node);
|
||||
}
|
||||
if (node instanceof MongoAccountTreeItem) {
|
||||
if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) {
|
||||
setConnectedNode(undefined);
|
||||
await node.refresh(actionContext);
|
||||
},
|
||||
);
|
||||
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'azureDatabases.detachDatabaseAccount',
|
||||
async (actionContext: IActionContext & ITreeItemPickerContext, node?: AzExtTreeItem) => {
|
||||
const children = await ext.attachedAccountsNode.loadAllChildren(actionContext);
|
||||
if (children[0].contextValue === 'cosmosDBAttachDatabaseAccount') {
|
||||
const message = localize('noAttachedAccounts', 'There are no Attached Accounts.');
|
||||
void vscode.window.showInformationMessage(message);
|
||||
} else {
|
||||
if (!node) {
|
||||
node = await ext.rgApi.workspaceResourceTree.showTreeItemPicker<AzExtTreeItem>(
|
||||
cosmosDBTopLevelContextValues.map((val: string) => (val += AttachedAccountSuffix)),
|
||||
actionContext,
|
||||
);
|
||||
}
|
||||
if (node instanceof MongoAccountTreeItem) {
|
||||
if (ext.connectedMongoDB && node.fullId === ext.connectedMongoDB.parent.fullId) {
|
||||
setConnectedNode(undefined);
|
||||
await node.refresh(actionContext);
|
||||
}
|
||||
}
|
||||
await ext.attachedAccountsNode.detach(node);
|
||||
await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode);
|
||||
}
|
||||
await ext.attachedAccountsNode.detach(node);
|
||||
await ext.rgApi.workspaceResourceTree.refresh(actionContext, ext.attachedAccountsNode);
|
||||
}
|
||||
});
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.importDocument', async (actionContext: IActionContext, selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem, uris: vscode.Uri[]) => {
|
||||
if (selectedNode instanceof vscode.Uri) {
|
||||
await importDocuments(actionContext, uris || [selectedNode], undefined);
|
||||
} else {
|
||||
await importDocuments(actionContext, undefined, selectedNode);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.importDocument',
|
||||
async (
|
||||
actionContext: IActionContext,
|
||||
selectedNode: vscode.Uri | MongoCollectionTreeItem | DocDBCollectionTreeItem,
|
||||
uris: vscode.Uri[],
|
||||
) => {
|
||||
if (selectedNode instanceof vscode.Uri) {
|
||||
await importDocuments(actionContext, uris || [selectedNode], undefined);
|
||||
} else {
|
||||
await importDocuments(actionContext, undefined, selectedNode);
|
||||
}
|
||||
},
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.copyConnectionString', cosmosDBCopyConnectionString);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.openDocument', async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => {
|
||||
if (!node) {
|
||||
node = await ext.rgApi.pickAppResource<MongoDocumentTreeItem | DocDBDocumentTreeItem>(actionContext, {
|
||||
filter: [
|
||||
cosmosMongoFilter,
|
||||
sqlFilter
|
||||
],
|
||||
expectedChildContextValue: [MongoDocumentTreeItem.contextValue, DocDBDocumentTreeItem.contextValue]
|
||||
});
|
||||
}
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.openDocument',
|
||||
async (actionContext: IActionContext, node?: MongoDocumentTreeItem | DocDBDocumentTreeItem) => {
|
||||
if (!node) {
|
||||
node = await ext.rgApi.pickAppResource<MongoDocumentTreeItem | DocDBDocumentTreeItem>(
|
||||
actionContext,
|
||||
{
|
||||
filter: [cosmosMongoFilter, sqlFilter],
|
||||
expectedChildContextValue: [
|
||||
MongoDocumentTreeItem.contextValue,
|
||||
DocDBDocumentTreeItem.contextValue,
|
||||
],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619
|
||||
ext.fileSystem.fireChangedEvent(node);
|
||||
await ext.fileSystem.showTextDocument(node);
|
||||
}, doubleClickDebounceDelay);
|
||||
registerCommandWithTreeNodeUnwrapping('azureDatabases.update', async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri));
|
||||
registerCommandWithTreeNodeUnwrapping('azureDatabases.loadMore', async (actionContext: IActionContext, node: AzExtTreeItem) => await ext.rgApi.appResourceTree.loadMore(node, actionContext));
|
||||
// Clear un-uploaded local changes to the document before opening https://github.com/microsoft/vscode-cosmosdb/issues/1619
|
||||
ext.fileSystem.fireChangedEvent(node);
|
||||
await ext.fileSystem.showTextDocument(node);
|
||||
},
|
||||
doubleClickDebounceDelay,
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'azureDatabases.update',
|
||||
async (_actionContext: IActionContext, uri: vscode.Uri) => await ext.fileSystem.updateWithoutPrompt(uri),
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'azureDatabases.loadMore',
|
||||
async (actionContext: IActionContext, node: AzExtTreeItem) =>
|
||||
await ext.rgApi.appResourceTree.loadMore(node, actionContext),
|
||||
);
|
||||
registerEvent(
|
||||
'cosmosDB.onDidChangeConfiguration',
|
||||
vscode.workspace.onDidChangeConfiguration,
|
||||
async (actionContext: IActionContext, event: vscode.ConfigurationChangeEvent) => {
|
||||
actionContext.telemetry.properties.isActivationEvent = "true";
|
||||
actionContext.telemetry.properties.isActivationEvent = 'true';
|
||||
actionContext.errorHandling.suppressDisplay = true;
|
||||
if (event.affectsConfiguration(ext.settingsKeys.documentLabelFields)) {
|
||||
await vscode.commands.executeCommand("azureDatabases.refresh");
|
||||
await vscode.commands.executeCommand('azureDatabases.refresh');
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Suppress "Report an Issue" button for all errors in favor of the command
|
||||
registerErrorHandler(c => c.errorHandling.suppressReportIssue = true);
|
||||
registerErrorHandler((c) => (c.errorHandling.suppressReportIssue = true));
|
||||
registerReportIssueCommand('azureDatabases.reportIssue');
|
||||
});
|
||||
|
||||
return createApiProvider([<AzureExtensionApi>{
|
||||
findTreeItem,
|
||||
pickTreeItem,
|
||||
revealTreeItem,
|
||||
apiVersion: '1.2.0'
|
||||
}]);
|
||||
return createApiProvider([
|
||||
<AzureExtensionApi>{
|
||||
findTreeItem,
|
||||
pickTreeItem,
|
||||
revealTreeItem,
|
||||
apiVersion: '1.2.0',
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// this method is called when your extension is deactivated
|
||||
|
@ -174,7 +254,10 @@ export function deactivateInternal(): void {
|
|||
|
||||
export async function createServer(context: IActionContext, node?: SubscriptionTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
node = await ext.rgApi.appResourceTree.showTreeItemPicker<SubscriptionTreeItem>(SubscriptionTreeItem.contextValue, context);
|
||||
node = await ext.rgApi.appResourceTree.showTreeItemPicker<SubscriptionTreeItem>(
|
||||
SubscriptionTreeItem.contextValue,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
await SubscriptionTreeItem.createChild(context, node);
|
||||
|
@ -185,28 +268,21 @@ export async function deleteAccount(context: IActionContext, node?: AzExtTreeIte
|
|||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await ext.rgApi.pickAppResource<AzExtTreeItem>(context, {
|
||||
filter: [
|
||||
cosmosMongoFilter,
|
||||
cosmosTableFilter,
|
||||
cosmosGremlinFilter,
|
||||
sqlFilter
|
||||
]
|
||||
filter: [cosmosMongoFilter, cosmosTableFilter, cosmosGremlinFilter, sqlFilter],
|
||||
});
|
||||
}
|
||||
|
||||
await deleteDatabaseAccount(context, node, false)
|
||||
await deleteDatabaseAccount(context, node, false);
|
||||
}
|
||||
|
||||
export async function cosmosDBCopyConnectionString(context: IActionContext, node?: MongoAccountTreeItem | DocDBAccountTreeItemBase): Promise<void> {
|
||||
export async function cosmosDBCopyConnectionString(
|
||||
context: IActionContext,
|
||||
node?: MongoAccountTreeItem | DocDBAccountTreeItemBase,
|
||||
): Promise<void> {
|
||||
const message = 'The connection string has been copied to the clipboard';
|
||||
if (!node) {
|
||||
node = await ext.rgApi.pickAppResource<MongoAccountTreeItem | DocDBAccountTreeItemBase>(context, {
|
||||
filter: [
|
||||
cosmosMongoFilter,
|
||||
cosmosTableFilter,
|
||||
cosmosGremlinFilter,
|
||||
sqlFilter
|
||||
]
|
||||
filter: [cosmosMongoFilter, cosmosTableFilter, cosmosGremlinFilter, sqlFilter],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,22 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeDataProvider, AzExtTreeItem, IAzExtLogOutputChannel } from "@microsoft/vscode-azext-utils";
|
||||
import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi";
|
||||
import { ExtensionContext, SecretStorage, TreeView } from "vscode";
|
||||
import { DatabasesFileSystem } from "./DatabasesFileSystem";
|
||||
import { NoSqlCodeLensProvider } from "./docdb/NoSqlCodeLensProvider";
|
||||
import { MongoDBLanguageClient } from "./mongo/languageClient";
|
||||
import { MongoCodeLensProvider } from "./mongo/services/MongoCodeLensProvider";
|
||||
import { MongoDatabaseTreeItem } from "./mongo/tree/MongoDatabaseTreeItem";
|
||||
import { PostgresCodeLensProvider } from "./postgres/services/PostgresCodeLensProvider";
|
||||
import { PostgresDatabaseTreeItem } from "./postgres/tree/PostgresDatabaseTreeItem";
|
||||
import { AttachedAccountsTreeItem } from "./tree/AttachedAccountsTreeItem";
|
||||
import { AzureAccountTreeItemWithAttached } from "./tree/AzureAccountTreeItemWithAttached";
|
||||
import {
|
||||
type AzExtTreeDataProvider,
|
||||
type AzExtTreeItem,
|
||||
type IAzExtLogOutputChannel,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { type AzureHostExtensionApi } from '@microsoft/vscode-azext-utils/hostapi';
|
||||
import { type ExtensionContext, type SecretStorage, type TreeView } from 'vscode';
|
||||
import { type DatabasesFileSystem } from './DatabasesFileSystem';
|
||||
import { type NoSqlCodeLensProvider } from './docdb/NoSqlCodeLensProvider';
|
||||
import { type MongoDBLanguageClient } from './mongo/languageClient';
|
||||
import { type MongoCodeLensProvider } from './mongo/services/MongoCodeLensProvider';
|
||||
import { type MongoDatabaseTreeItem } from './mongo/tree/MongoDatabaseTreeItem';
|
||||
import { type PostgresCodeLensProvider } from './postgres/services/PostgresCodeLensProvider';
|
||||
import { type PostgresDatabaseTreeItem } from './postgres/tree/PostgresDatabaseTreeItem';
|
||||
import { type AttachedAccountsTreeItem } from './tree/AttachedAccountsTreeItem';
|
||||
import { type AzureAccountTreeItemWithAttached } from './tree/AzureAccountTreeItemWithAttached';
|
||||
|
||||
/**
|
||||
* Namespace for common variables used throughout the extension. They must be initialized in the activate() method of extension.ts
|
||||
|
@ -47,7 +51,7 @@ export namespace ext {
|
|||
export const batchSize = 'azureDatabases.batchSize';
|
||||
|
||||
export namespace vsCode {
|
||||
export const proxyStrictSSL = "http.proxyStrictSSL";
|
||||
export const proxyStrictSSL = 'http.proxyStrictSSL';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { apiUtils } from "@microsoft/vscode-azext-utils";
|
||||
import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi";
|
||||
import { Extension, extensions } from "vscode";
|
||||
import { localize } from "./utils/localize";
|
||||
import { type apiUtils } from '@microsoft/vscode-azext-utils';
|
||||
import { type AzureHostExtensionApi } from '@microsoft/vscode-azext-utils/hostapi';
|
||||
import { extensions, type Extension } from 'vscode';
|
||||
import { localize } from './utils/localize';
|
||||
|
||||
export async function getApiExport<T>(extensionId: string): Promise<T | undefined> {
|
||||
const extension: Extension<T> | undefined = extensions.getExtension(extensionId);
|
||||
|
@ -22,7 +22,9 @@ export async function getApiExport<T>(extensionId: string): Promise<T | undefine
|
|||
}
|
||||
|
||||
export async function getResourceGroupsApi(): Promise<AzureHostExtensionApi> {
|
||||
const rgApiProvider = await getApiExport<apiUtils.AzureExtensionApiProvider>('ms-azuretools.vscode-azureresourcegroups');
|
||||
const rgApiProvider = await getApiExport<apiUtils.AzureExtensionApiProvider>(
|
||||
'ms-azuretools.vscode-azureresourcegroups',
|
||||
);
|
||||
if (rgApiProvider) {
|
||||
return rgApiProvider.getApi<AzureHostExtensionApi>('^0.0.1');
|
||||
} else {
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CosmosDBManagementClient } from '@azure/arm-cosmosdb';
|
||||
import { type CosmosDBManagementClient } from '@azure/arm-cosmosdb';
|
||||
import { nonNullValue } from '../utils/nonNull';
|
||||
import { IGremlinEndpoint } from '../vscode-cosmosdbgraph.api';
|
||||
import { type IGremlinEndpoint } from '../vscode-cosmosdbgraph.api';
|
||||
|
||||
export async function tryGetGremlinEndpointFromAzure(client: CosmosDBManagementClient, resourceGroup: string, account: string): Promise<IGremlinEndpoint | undefined> {
|
||||
export async function tryGetGremlinEndpointFromAzure(
|
||||
client: CosmosDBManagementClient,
|
||||
resourceGroup: string,
|
||||
account: string,
|
||||
): Promise<IGremlinEndpoint | undefined> {
|
||||
// Only 'bodyOfText' property of 'response' contains the 'gremlinEndpoint' property in the @azure/arm-cosmosdb@9 sdk
|
||||
const response = await client.databaseAccounts.get(resourceGroup, account);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
||||
|
@ -39,9 +43,12 @@ export function getPossibleGremlinEndpoints(documentEndpoint: string): IGremlinE
|
|||
* @param url An account URL such as 'https://<graphname>.documents.azure.com:443/'
|
||||
*/
|
||||
function parseEndpointUrl(url: string): IGremlinEndpoint {
|
||||
const [, protocol, host, , portString] = nonNullValue(url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/), 'urlMatch');
|
||||
console.assert(!!protocol && !!host, "Unexpected endpoint format");
|
||||
const port = parseInt(portString || "443", 10);
|
||||
console.assert(port > 0, "Unexpected port");
|
||||
return { host, port, ssl: protocol.toLowerCase() === "https" };
|
||||
const [, protocol, host, , portString] = nonNullValue(
|
||||
url.match(/^([^:]+):\/\/([^:]+)(:([0-9]+))?\/?$/),
|
||||
'urlMatch',
|
||||
);
|
||||
console.assert(!!protocol && !!host, 'Unexpected endpoint format');
|
||||
const port = parseInt(portString || '443', 10);
|
||||
console.assert(port > 0, 'Unexpected port');
|
||||
return { host, port, ssl: protocol.toLowerCase() === 'https' };
|
||||
}
|
||||
|
|
|
@ -3,39 +3,54 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, registerCommandWithTreeNodeUnwrapping } from "@microsoft/vscode-azext-utils";
|
||||
import {
|
||||
registerCommandWithTreeNodeUnwrapping,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type ITreeItemPickerContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { cosmosGremlinFilter, doubleClickDebounceDelay } from '../constants';
|
||||
import { ext } from '../extensionVariables';
|
||||
import { GraphAccountTreeItem } from "./tree/GraphAccountTreeItem";
|
||||
import { GraphCollectionTreeItem } from "./tree/GraphCollectionTreeItem";
|
||||
import { GraphDatabaseTreeItem } from "./tree/GraphDatabaseTreeItem";
|
||||
import { GraphTreeItem } from "./tree/GraphTreeItem";
|
||||
import { type GraphAccountTreeItem } from './tree/GraphAccountTreeItem';
|
||||
import { GraphCollectionTreeItem } from './tree/GraphCollectionTreeItem';
|
||||
import { GraphDatabaseTreeItem } from './tree/GraphDatabaseTreeItem';
|
||||
import { GraphTreeItem } from './tree/GraphTreeItem';
|
||||
|
||||
export function registerGraphCommands(): void {
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraphDatabase', createGraphDatabase);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.createGraph', createGraph);
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraphDatabase', async (context: IActionContext, node?: GraphDatabaseTreeItem) => {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphDatabaseTreeItem>(context, GraphDatabaseTreeItem.contextValue);
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
});
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.deleteGraph', async (context: IActionContext, node?: GraphCollectionTreeItem) => {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphCollectionTreeItem>(context, GraphCollectionTreeItem.contextValue);
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
});
|
||||
registerCommandWithTreeNodeUnwrapping('cosmosDB.openGraphExplorer', async (context: IActionContext, node: GraphTreeItem) => {
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphTreeItem>(context, GraphTreeItem.contextValue);
|
||||
}
|
||||
await node.showExplorer(context);
|
||||
}, doubleClickDebounceDelay);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.deleteGraphDatabase',
|
||||
async (context: IActionContext, node?: GraphDatabaseTreeItem) => {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphDatabaseTreeItem>(context, GraphDatabaseTreeItem.contextValue);
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
},
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.deleteGraph',
|
||||
async (context: IActionContext, node?: GraphCollectionTreeItem) => {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
suppressCreateContext.suppressCreatePick = true;
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphCollectionTreeItem>(context, GraphCollectionTreeItem.contextValue);
|
||||
}
|
||||
await node.deleteTreeItem(context);
|
||||
},
|
||||
);
|
||||
registerCommandWithTreeNodeUnwrapping(
|
||||
'cosmosDB.openGraphExplorer',
|
||||
async (context: IActionContext, node: GraphTreeItem) => {
|
||||
if (!node) {
|
||||
node = await pickGraph<GraphTreeItem>(context, GraphTreeItem.contextValue);
|
||||
}
|
||||
await node.showExplorer(context);
|
||||
},
|
||||
doubleClickDebounceDelay,
|
||||
);
|
||||
}
|
||||
|
||||
export async function createGraphDatabase(context: IActionContext, node?: GraphAccountTreeItem): Promise<void> {
|
||||
|
@ -52,11 +67,12 @@ export async function createGraph(context: IActionContext, node?: GraphDatabaseT
|
|||
await node.createChild(context);
|
||||
}
|
||||
|
||||
async function pickGraph<T extends AzExtTreeItem>(context: IActionContext, expectedContextValue?: string | RegExp | (string | RegExp)[]): Promise<T> {
|
||||
async function pickGraph<T extends AzExtTreeItem>(
|
||||
context: IActionContext,
|
||||
expectedContextValue?: string | RegExp | (string | RegExp)[],
|
||||
): Promise<T> {
|
||||
return await ext.rgApi.pickAppResource<T>(context, {
|
||||
filter: [
|
||||
cosmosGremlinFilter
|
||||
],
|
||||
expectedChildContextValue: expectedContextValue
|
||||
filter: [cosmosGremlinFilter],
|
||||
expectedChildContextValue: expectedContextValue,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import { DatabaseDefinition, Resource } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import { CosmosDBCredential } from '../../docdb/getCosmosClient';
|
||||
import { type DatabaseAccountGetResults } from '@azure/arm-cosmosdb/src/models';
|
||||
import { type DatabaseDefinition, type Resource } from '@azure/cosmos';
|
||||
import { type AzExtParentTreeItem } from '@microsoft/vscode-azext-utils';
|
||||
import { type CosmosDBCredential } from '../../docdb/getCosmosClient';
|
||||
import { DocDBAccountTreeItemBase } from '../../docdb/tree/DocDBAccountTreeItemBase';
|
||||
import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem';
|
||||
import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem';
|
||||
import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api';
|
||||
import { type IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api';
|
||||
import { GraphCollectionTreeItem } from './GraphCollectionTreeItem';
|
||||
import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem';
|
||||
import { GraphTreeItem } from './GraphTreeItem';
|
||||
|
||||
export class GraphAccountTreeItem extends DocDBAccountTreeItemBase {
|
||||
public static contextValue: string = "cosmosDBGraphAccount";
|
||||
public static contextValue: string = 'cosmosDBGraphAccount';
|
||||
public contextValue: string = GraphAccountTreeItem.contextValue;
|
||||
|
||||
constructor(
|
||||
|
@ -27,7 +27,7 @@ export class GraphAccountTreeItem extends DocDBAccountTreeItemBase {
|
|||
private _gremlinEndpoint: IGremlinEndpoint | undefined,
|
||||
credentials: CosmosDBCredential[],
|
||||
isEmulator: boolean | undefined,
|
||||
readonly databaseAccount?: DatabaseAccountGetResults
|
||||
readonly databaseAccount?: DatabaseAccountGetResults,
|
||||
) {
|
||||
super(parent, id, label, documentEndpoint, credentials, isEmulator, databaseAccount);
|
||||
this.valuesToMask.push(documentEndpoint);
|
||||
|
|
|
@ -3,17 +3,23 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Container, ContainerDefinition, CosmosClient, Resource } from '@azure/cosmos';
|
||||
import { AzExtParentTreeItem, AzExtTreeItem, DialogResponses, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import { type Container, type ContainerDefinition, type CosmosClient, type Resource } from '@azure/cosmos';
|
||||
import {
|
||||
AzExtParentTreeItem,
|
||||
DialogResponses,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type TreeItemIconPath,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { DocDBStoredProceduresTreeItem } from '../../docdb/tree/DocDBStoredProceduresTreeItem';
|
||||
import { DocDBStoredProcedureTreeItem } from '../../docdb/tree/DocDBStoredProcedureTreeItem';
|
||||
import { IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot';
|
||||
import { GraphDatabaseTreeItem } from './GraphDatabaseTreeItem';
|
||||
import { type IDocDBTreeRoot } from '../../docdb/tree/IDocDBTreeRoot';
|
||||
import { type GraphDatabaseTreeItem } from './GraphDatabaseTreeItem';
|
||||
import { GraphTreeItem } from './GraphTreeItem';
|
||||
|
||||
export class GraphCollectionTreeItem extends AzExtParentTreeItem {
|
||||
public static contextValue: string = "cosmosDBGraph";
|
||||
public static contextValue: string = 'cosmosDBGraph';
|
||||
public readonly contextValue: string = GraphCollectionTreeItem.contextValue;
|
||||
public readonly parent: GraphDatabaseTreeItem;
|
||||
|
||||
|
@ -59,7 +65,11 @@ export class GraphCollectionTreeItem extends AzExtParentTreeItem {
|
|||
|
||||
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
|
||||
const message: string = `Are you sure you want to delete graph '${this.label}' and its contents?`;
|
||||
await context.ui.showWarningMessage(message, { modal: true, stepName: 'deleteGraphCollection' }, DialogResponses.deleteResponse);
|
||||
await context.ui.showWarningMessage(
|
||||
message,
|
||||
{ modal: true, stepName: 'deleteGraphCollection' },
|
||||
DialogResponses.deleteResponse,
|
||||
);
|
||||
const client = this.root.getCosmosClient();
|
||||
await this.getContainerClient(client).delete();
|
||||
}
|
||||
|
@ -81,7 +91,6 @@ export class GraphCollectionTreeItem extends AzExtParentTreeItem {
|
|||
}
|
||||
|
||||
public getContainerClient(client: CosmosClient): Container {
|
||||
return (this.parent.getDatabaseClient(client)).container(this.id);
|
||||
|
||||
return this.parent.getDatabaseClient(client).container(this.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,20 +3,30 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContainerDefinition, CosmosClient, Database, DatabaseDefinition, Resource } from '@azure/cosmos';
|
||||
import { IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
type ContainerDefinition,
|
||||
type CosmosClient,
|
||||
type Database,
|
||||
type DatabaseDefinition,
|
||||
type Resource,
|
||||
} from '@azure/cosmos';
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { DocDBDatabaseTreeItemBase } from '../../docdb/tree/DocDBDatabaseTreeItemBase';
|
||||
import { IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api';
|
||||
import { type IGremlinEndpoint } from '../../vscode-cosmosdbgraph.api';
|
||||
import { getPossibleGremlinEndpoints } from '../gremlinEndpoints';
|
||||
import { GraphAccountTreeItem } from './GraphAccountTreeItem';
|
||||
import { type GraphAccountTreeItem } from './GraphAccountTreeItem';
|
||||
import { GraphCollectionTreeItem } from './GraphCollectionTreeItem';
|
||||
|
||||
export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase {
|
||||
public static contextValue: string = "cosmosDBGraphDatabase";
|
||||
public static contextValue: string = 'cosmosDBGraphDatabase';
|
||||
public readonly contextValue: string = GraphDatabaseTreeItem.contextValue;
|
||||
public readonly childTypeLabel: string = 'Graph';
|
||||
|
||||
constructor(parent: GraphAccountTreeItem, private _gremlinEndpoint: IGremlinEndpoint | undefined, database: DatabaseDefinition & Resource) {
|
||||
constructor(
|
||||
parent: GraphAccountTreeItem,
|
||||
private _gremlinEndpoint: IGremlinEndpoint | undefined,
|
||||
database: DatabaseDefinition & Resource,
|
||||
) {
|
||||
super(parent, database);
|
||||
}
|
||||
|
||||
|
@ -35,7 +45,6 @@ export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase {
|
|||
|
||||
public getDatabaseClient(client: CosmosClient): Database {
|
||||
return client.database(this.id);
|
||||
|
||||
}
|
||||
|
||||
protected override async getNewPartitionKey(context: IActionContext): Promise<string | undefined> {
|
||||
|
@ -43,7 +52,7 @@ export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase {
|
|||
prompt: 'Enter the partition key for the collection, or leave blank for fixed size.',
|
||||
stepName: 'partitionKeyForCollection',
|
||||
validateInput: this.validatePartitionKey,
|
||||
placeHolder: 'e.g. /address'
|
||||
placeHolder: 'e.g. /address',
|
||||
});
|
||||
|
||||
if (partitionKey && partitionKey.length && partitionKey[0] !== '/') {
|
||||
|
@ -55,10 +64,10 @@ export class GraphDatabaseTreeItem extends DocDBDatabaseTreeItemBase {
|
|||
|
||||
protected validatePartitionKey(key: string): string | undefined {
|
||||
if (/[#?\\]/.test(key)) {
|
||||
return "Cannot contain these characters: ?,#,\\, etc.";
|
||||
return 'Cannot contain these characters: ?,#,\\, etc.';
|
||||
}
|
||||
if (/.+\//.test(key)) {
|
||||
return "Cannot be a nested path";
|
||||
return 'Cannot be a nested path';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContainerDefinition, Resource } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import { type ContainerDefinition, type Resource } from '@azure/cosmos';
|
||||
import { AzExtTreeItem, type IActionContext, type TreeItemIconPath } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { openUrl } from '../../utils/openUrl';
|
||||
import { GraphCollectionTreeItem } from './GraphCollectionTreeItem';
|
||||
import { type GraphCollectionTreeItem } from './GraphCollectionTreeItem';
|
||||
|
||||
const alternativeGraphVisualizationToolsDocLink = "https://aka.ms/cosmosdb-graph-alternative-tools";
|
||||
const alternativeGraphVisualizationToolsDocLink = 'https://aka.ms/cosmosdb-graph-alternative-tools';
|
||||
|
||||
export class GraphTreeItem extends AzExtTreeItem {
|
||||
public static contextValue: string = "cosmosDBGraphGraph";
|
||||
public static contextValue: string = 'cosmosDBGraphGraph';
|
||||
public readonly contextValue: string = GraphTreeItem.contextValue;
|
||||
public readonly parent: GraphCollectionTreeItem;
|
||||
public suppressMaskLabel = true;
|
||||
|
@ -31,7 +31,7 @@ export class GraphTreeItem extends AzExtTreeItem {
|
|||
}
|
||||
|
||||
public get label(): string {
|
||||
return "Graph";
|
||||
return 'Graph';
|
||||
}
|
||||
|
||||
public get link(): string {
|
||||
|
@ -44,11 +44,8 @@ export class GraphTreeItem extends AzExtTreeItem {
|
|||
|
||||
public async showExplorer(_context: IActionContext): Promise<void> {
|
||||
const message: string = localize('mustInstallGraph', 'Cosmos DB Graph extension has been retired.');
|
||||
const alternativeToolsOption = "Alternative Tools";
|
||||
const result = await vscode.window.showErrorMessage(
|
||||
message,
|
||||
alternativeToolsOption
|
||||
);
|
||||
const alternativeToolsOption = 'Alternative Tools';
|
||||
const result = await vscode.window.showErrorMessage(message, alternativeToolsOption);
|
||||
if (result === alternativeToolsOption) {
|
||||
await openUrl(alternativeGraphVisualizationToolsDocLink);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RecognitionException } from 'antlr4ts';
|
||||
import * as vscode from 'vscode';
|
||||
import { type RecognitionException } from 'antlr4ts';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
export interface MongoCommand {
|
||||
range: vscode.Range;
|
||||
|
@ -12,7 +12,7 @@ export interface MongoCommand {
|
|||
collection?: string;
|
||||
name?: string;
|
||||
arguments?: string[];
|
||||
argumentObjects?: Object[];
|
||||
argumentObjects?: object[];
|
||||
errors?: ErrorDescription[];
|
||||
chained?: boolean;
|
||||
}
|
||||
|
|
|
@ -3,14 +3,20 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, IParsedError, openReadOnlyContent, parseError, ReadOnlyContent } from '@microsoft/vscode-azext-utils';
|
||||
import {
|
||||
openReadOnlyContent,
|
||||
parseError,
|
||||
type IActionContext,
|
||||
type IParsedError,
|
||||
type ReadOnlyContent,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream';
|
||||
import { CommonTokenStream } from 'antlr4ts/CommonTokenStream';
|
||||
import { ErrorNode } from 'antlr4ts/tree/ErrorNode';
|
||||
import { ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { type ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
||||
import { EJSON, ObjectId } from 'bson';
|
||||
import { Collection } from 'mongodb';
|
||||
import { type Collection } from 'mongodb';
|
||||
import { EOL } from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from '../extensionVariables';
|
||||
|
@ -21,18 +27,18 @@ import { LexerErrorListener, ParserErrorListener } from './errorListeners';
|
|||
import { mongoLexer } from './grammar/mongoLexer';
|
||||
import * as mongoParser from './grammar/mongoParser';
|
||||
import { MongoVisitor } from './grammar/visitors';
|
||||
import { ErrorDescription, MongoCommand } from './MongoCommand';
|
||||
import { type ErrorDescription, type MongoCommand } from './MongoCommand';
|
||||
import { MongoCollectionTreeItem } from './tree/MongoCollectionTreeItem';
|
||||
import { MongoDatabaseTreeItem, stripQuotes } from './tree/MongoDatabaseTreeItem';
|
||||
import { IMongoDocument, MongoDocumentTreeItem } from './tree/MongoDocumentTreeItem';
|
||||
import { stripQuotes, type MongoDatabaseTreeItem } from './tree/MongoDatabaseTreeItem';
|
||||
import { MongoDocumentTreeItem, type IMongoDocument } from './tree/MongoDocumentTreeItem';
|
||||
|
||||
const notInScrapbookMessage = "You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command.";
|
||||
const notInScrapbookMessage = 'You must have a MongoDB scrapbook (*.mongo) open to run a MongoDB command.';
|
||||
|
||||
export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] {
|
||||
const commands = getAllCommandsFromTextDocument(document);
|
||||
const errors: vscode.Diagnostic[] = [];
|
||||
for (const command of commands) {
|
||||
for (const error of (command.errors || [])) {
|
||||
for (const error of command.errors || []) {
|
||||
const diagnostic = new vscode.Diagnostic(error.range, error.message);
|
||||
errors.push(diagnostic);
|
||||
}
|
||||
|
@ -42,12 +48,15 @@ export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vsc
|
|||
}
|
||||
|
||||
export async function executeAllCommandsFromActiveEditor(context: IActionContext): Promise<void> {
|
||||
ext.outputChannel.appendLog("Executing all commands in scrapbook...");
|
||||
ext.outputChannel.appendLog('Executing all commands in scrapbook...');
|
||||
const commands = getAllCommandsFromActiveEditor();
|
||||
await executeCommands(context, commands);
|
||||
}
|
||||
|
||||
export async function executeCommandFromActiveEditor(context: IActionContext, position?: vscode.Position): Promise<void> {
|
||||
export async function executeCommandFromActiveEditor(
|
||||
context: IActionContext,
|
||||
position?: vscode.Position,
|
||||
): Promise<void> {
|
||||
const commands = getAllCommandsFromActiveEditor();
|
||||
const command = findCommandAtPosition(commands, position || vscode.window.activeTextEditor?.selection.start);
|
||||
return await executeCommand(context, command);
|
||||
|
@ -70,7 +79,9 @@ export function getAllCommandsFromTextDocument(document: vscode.TextDocument): M
|
|||
async function executeCommands(context: IActionContext, commands: MongoCommand[]): Promise<void> {
|
||||
const label: string = 'Scrapbook-execute-all-results';
|
||||
const fullId: string = `${ext.connectedMongoDB?.fullId}/${label}`;
|
||||
const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', { viewColumn: vscode.ViewColumn.Beside });
|
||||
const readOnlyContent: ReadOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.txt', {
|
||||
viewColumn: vscode.ViewColumn.Beside,
|
||||
});
|
||||
|
||||
for (const command of commands) {
|
||||
try {
|
||||
|
@ -87,23 +98,34 @@ async function executeCommands(context: IActionContext, commands: MongoCommand[]
|
|||
}
|
||||
}
|
||||
|
||||
async function executeCommand(context: IActionContext, command: MongoCommand, readOnlyContent?: ReadOnlyContent): Promise<void> {
|
||||
async function executeCommand(
|
||||
context: IActionContext,
|
||||
command: MongoCommand,
|
||||
readOnlyContent?: ReadOnlyContent,
|
||||
): Promise<void> {
|
||||
if (command) {
|
||||
try {
|
||||
context.telemetry.properties.command = command.name;
|
||||
context.telemetry.properties.argsCount = String(command.arguments ? command.arguments.length : 0);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
const database = ext.connectedMongoDB;
|
||||
if (!database) {
|
||||
throw new Error('Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item');
|
||||
throw new Error(
|
||||
'Please select a MongoDB database to run against by selecting it in the explorer and selecting the "Connect" context menu item',
|
||||
);
|
||||
}
|
||||
if (command.errors && command.errors.length > 0) {
|
||||
//Currently, we take the first error pushed. Tests correlate that the parser visits errors in left-to-right, top-to-bottom.
|
||||
const err = command.errors[0];
|
||||
throw new Error(localize('unableToParseSyntax', `Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`));
|
||||
throw new Error(
|
||||
localize(
|
||||
'unableToParseSyntax',
|
||||
`Unable to parse syntax. Error near line ${err.range.start.line + 1}, column ${err.range.start.character + 1}: "${err.message}"`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// we don't handle chained commands so we can only handle "find" if isn't chained
|
||||
|
@ -118,7 +140,7 @@ async function executeCommand(context: IActionContext, command: MongoCommand, re
|
|||
} else {
|
||||
const result = await database.executeCommand(command, context);
|
||||
if (command.name === 'findOne') {
|
||||
if (result === "null") {
|
||||
if (result === 'null') {
|
||||
throw new Error(`Could not find any documents`);
|
||||
}
|
||||
|
||||
|
@ -127,7 +149,10 @@ async function executeCommand(context: IActionContext, command: MongoCommand, re
|
|||
const collectionName: string = nonNullProp(command, 'collection');
|
||||
|
||||
const collectionId: string = `${database.fullId}/${collectionName}`;
|
||||
const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(collectionId, context);
|
||||
const colNode: MongoCollectionTreeItem | undefined = await ext.rgApi.appResourceTree.findTreeItem(
|
||||
collectionId,
|
||||
context,
|
||||
);
|
||||
if (!colNode) {
|
||||
throw new Error(localize('failedToFind', 'Failed to find collection "{0}".', collectionName));
|
||||
}
|
||||
|
@ -139,7 +164,9 @@ async function executeCommand(context: IActionContext, command: MongoCommand, re
|
|||
} else {
|
||||
const label: string = 'Scrapbook-results';
|
||||
const fullId: string = `${database.fullId}/${label}`;
|
||||
await openReadOnlyContent({ label, fullId }, result, '.json', { viewColumn: vscode.ViewColumn.Beside });
|
||||
await openReadOnlyContent({ label, fullId }, result, '.json', {
|
||||
viewColumn: vscode.ViewColumn.Beside,
|
||||
});
|
||||
}
|
||||
|
||||
await refreshTreeAfterCommand(database, command, context);
|
||||
|
@ -150,11 +177,22 @@ async function executeCommand(context: IActionContext, command: MongoCommand, re
|
|||
}
|
||||
}
|
||||
|
||||
async function refreshTreeAfterCommand(database: MongoDatabaseTreeItem, command: MongoCommand, context: IActionContext): Promise<void> {
|
||||
async function refreshTreeAfterCommand(
|
||||
database: MongoDatabaseTreeItem,
|
||||
command: MongoCommand,
|
||||
context: IActionContext,
|
||||
): Promise<void> {
|
||||
if (command.name === 'drop') {
|
||||
await database.refresh(context);
|
||||
} else if (command.collection && command.name && /^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)) {
|
||||
const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(database.fullId + "/" + command.collection, context);
|
||||
} else if (
|
||||
command.collection &&
|
||||
command.name &&
|
||||
/^(insert|update|delete|replace|remove|write|bulkWrite)/i.test(command.name)
|
||||
) {
|
||||
const collectionNode = await ext.rgApi.appResourceTree.findTreeItem(
|
||||
database.fullId + '/' + command.collection,
|
||||
context,
|
||||
);
|
||||
if (collectionNode) {
|
||||
await collectionNode.refresh(context);
|
||||
}
|
||||
|
@ -194,7 +232,7 @@ export function getAllCommandsFromText(content: string): MongoCommand[] {
|
|||
collection: undefined,
|
||||
name: undefined,
|
||||
range: err.range,
|
||||
text: ""
|
||||
text: '',
|
||||
};
|
||||
emptyCommand.errors = [err];
|
||||
commands.push(emptyCommand);
|
||||
|
@ -230,12 +268,17 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length;
|
||||
const stop = nonNullProp(ctx, 'stop');
|
||||
this.commands.push({
|
||||
range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine),
|
||||
range: new vscode.Range(
|
||||
ctx.start.line - 1,
|
||||
ctx.start.charPositionInLine,
|
||||
stop.line - 1,
|
||||
stop.charPositionInLine,
|
||||
),
|
||||
text: ctx.text,
|
||||
name: '',
|
||||
arguments: [],
|
||||
argumentObjects: [],
|
||||
chained: funcCallCount > 1 ? true : false
|
||||
chained: funcCallCount > 1 ? true : false,
|
||||
});
|
||||
return super.visitCommand(ctx);
|
||||
}
|
||||
|
@ -247,7 +290,7 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
|
||||
public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] {
|
||||
if (ctx.parent instanceof mongoParser.CommandContext) {
|
||||
this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || "";
|
||||
this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || '';
|
||||
}
|
||||
return super.visitFunctionCall(ctx);
|
||||
}
|
||||
|
@ -268,7 +311,8 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
||||
ejsonParsed = EJSON.parse(escapeHandled);
|
||||
} catch (error) { //EJSON parse failed due to a wrong flag, etc.
|
||||
} catch (error) {
|
||||
//EJSON parse failed due to a wrong flag, etc.
|
||||
const parsedError: IParsedError = parseError(error);
|
||||
this.addErrorToCommand(parsedError.message, ctx);
|
||||
}
|
||||
|
@ -286,8 +330,10 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
return this.commands;
|
||||
}
|
||||
|
||||
//eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object {
|
||||
if (!ctx || ctx.childCount === 0) { //Base case and malformed statements
|
||||
if (!ctx || ctx.childCount === 0) {
|
||||
//Base case and malformed statements
|
||||
return {};
|
||||
}
|
||||
// In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4
|
||||
|
@ -308,10 +354,18 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
}
|
||||
}
|
||||
|
||||
private literalContextToObject(child: mongoParser.LiteralContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object {
|
||||
private literalContextToObject(
|
||||
child: mongoParser.LiteralContext,
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
//eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): Object {
|
||||
const text = child.text;
|
||||
const tokenType = child.start.type;
|
||||
const nonStringLiterals = [mongoParser.mongoParser.NullLiteral, mongoParser.mongoParser.BooleanLiteral, mongoParser.mongoParser.NumericLiteral];
|
||||
const nonStringLiterals = [
|
||||
mongoParser.mongoParser.NullLiteral,
|
||||
mongoParser.mongoParser.BooleanLiteral,
|
||||
mongoParser.mongoParser.NumericLiteral,
|
||||
];
|
||||
if (tokenType === mongoParser.mongoParser.StringLiteral) {
|
||||
return stripQuotes(text);
|
||||
} else if (tokenType === mongoParser.mongoParser.RegexLiteral) {
|
||||
|
@ -325,13 +379,17 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
}
|
||||
}
|
||||
|
||||
private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): Object {
|
||||
private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): object {
|
||||
const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext);
|
||||
if (!propertyNameAndValue) { // Argument is {}
|
||||
if (!propertyNameAndValue) {
|
||||
// Argument is {}
|
||||
return {};
|
||||
} else {
|
||||
const parsedObject: Object = {};
|
||||
const propertyAssignments = filterType(propertyNameAndValue.children, mongoParser.PropertyAssignmentContext);
|
||||
const parsedObject: object = {};
|
||||
const propertyAssignments = filterType(
|
||||
propertyNameAndValue.children,
|
||||
mongoParser.PropertyAssignmentContext,
|
||||
);
|
||||
for (const propertyAssignment of propertyAssignments) {
|
||||
const propertyAssignmentChildren = nonNullProp(propertyAssignment, 'children');
|
||||
const propertyName = <mongoParser.PropertyNameContext>propertyAssignmentChildren[0];
|
||||
|
@ -346,22 +404,34 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
const elementList = findType(child.children, mongoParser.ElementListContext);
|
||||
if (elementList) {
|
||||
const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return elementItems.map(this.contextToObject.bind(this));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private functionCallContextToObject(child: mongoParser.FunctionCallContext, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object {
|
||||
private functionCallContextToObject(
|
||||
child: mongoParser.FunctionCallContext,
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): Object {
|
||||
const functionTokens = child.children;
|
||||
const constructorCall: TerminalNode = nonNullValue(findType(functionTokens, TerminalNode), 'constructorCall');
|
||||
const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(findType(functionTokens, mongoParser.ArgumentsContext), 'argumentsToken');
|
||||
if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { //argumentsToken does not have '(' or ')'
|
||||
const argumentsToken: mongoParser.ArgumentsContext = nonNullValue(
|
||||
findType(functionTokens, mongoParser.ArgumentsContext),
|
||||
'argumentsToken',
|
||||
);
|
||||
if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) {
|
||||
//argumentsToken does not have '(' or ')'
|
||||
this.addErrorToCommand(`Expecting parentheses or quotes at '${constructorCall.text}'`, ctx);
|
||||
return {};
|
||||
}
|
||||
|
||||
const argumentContextArray: mongoParser.ArgumentContext[] = filterType(argumentsToken.children, mongoParser.ArgumentContext);
|
||||
const argumentContextArray: mongoParser.ArgumentContext[] = filterType(
|
||||
argumentsToken.children,
|
||||
mongoParser.ArgumentContext,
|
||||
);
|
||||
if (argumentContextArray.length > 1) {
|
||||
this.addErrorToCommand(`Too many arguments. Expecting 0 or 1 argument(s) to ${constructorCall}`, ctx);
|
||||
return {};
|
||||
|
@ -376,13 +446,21 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
case 'Date':
|
||||
return this.dateToObject(ctx, tokenText);
|
||||
default:
|
||||
this.addErrorToCommand(`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`, ctx);
|
||||
this.addErrorToCommand(
|
||||
`Unrecognized node type encountered. Could not parse ${constructorCall.text} as part of ${child.text}`,
|
||||
ctx,
|
||||
);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
private dateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} {
|
||||
const date: Date | {} = this.tryToConstructDate(ctx, tokenText);
|
||||
private dateToObject(
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
tokenText?: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): { $date: string } | Object {
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
const date: Date | Object = this.tryToConstructDate(ctx, tokenText);
|
||||
if (date instanceof Date) {
|
||||
return { $date: date.toString() };
|
||||
} else {
|
||||
|
@ -390,8 +468,13 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
}
|
||||
}
|
||||
|
||||
private isodateToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): { $date: string } | {} {
|
||||
const date: Date | {} = this.tryToConstructDate(ctx, tokenText, true);
|
||||
private isodateToObject(
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
tokenText?: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): { $date: string } | Object {
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
const date: Date | Object = this.tryToConstructDate(ctx, tokenText, true);
|
||||
|
||||
if (date instanceof Date) {
|
||||
return { $date: date.toISOString() };
|
||||
|
@ -400,8 +483,14 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
}
|
||||
}
|
||||
|
||||
private tryToConstructDate(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string, isIsodate: boolean = false): Date | {} {
|
||||
if (!tokenText) { // usage : ObjectID()
|
||||
private tryToConstructDate(
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
tokenText?: string,
|
||||
isIsodate: boolean = false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): Date | Object {
|
||||
if (!tokenText) {
|
||||
// usage : ObjectID()
|
||||
return new Date();
|
||||
} else {
|
||||
try {
|
||||
|
@ -423,10 +512,15 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
}
|
||||
}
|
||||
|
||||
private objectIdToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, tokenText?: string): Object {
|
||||
private objectIdToObject(
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
tokenText?: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): Object {
|
||||
let hexID: string;
|
||||
let constructedObject: ObjectId;
|
||||
if (!tokenText) { // usage : ObjectID()
|
||||
if (!tokenText) {
|
||||
// usage : ObjectID()
|
||||
constructedObject = new ObjectId();
|
||||
} else {
|
||||
hexID = stripQuotes(<string>tokenText);
|
||||
|
@ -441,30 +535,44 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
return { $oid: constructedObject.toString() };
|
||||
}
|
||||
|
||||
private regexLiteralContextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, text: string): Object {
|
||||
private regexLiteralContextToObject(
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
text: string,
|
||||
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
||||
): Object {
|
||||
const separator = text.lastIndexOf('/');
|
||||
const flags = separator !== text.length - 1 ? text.substring(separator + 1) : "";
|
||||
const flags = separator !== text.length - 1 ? text.substring(separator + 1) : '';
|
||||
const pattern = text.substring(1, separator);
|
||||
try {
|
||||
// validate the pattern and flags.
|
||||
// It is intended for the errors thrown here to be handled by the catch block.
|
||||
let tokenObject = new RegExp(pattern, flags);
|
||||
// eslint-disable-next-line no-self-assign, @typescript-eslint/no-unused-vars
|
||||
tokenObject = tokenObject;
|
||||
new RegExp(pattern, flags);
|
||||
// we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax
|
||||
return { $regex: this.regexToStringNotation(pattern), $options: flags };
|
||||
} catch (error) { //User may not have finished typing
|
||||
} catch (error) {
|
||||
//User may not have finished typing
|
||||
const parsedError: IParsedError = parseError(error);
|
||||
this.addErrorToCommand(parsedError.message, ctx);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
private addErrorToCommand(errorMessage: string, ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): void {
|
||||
private addErrorToCommand(
|
||||
errorMessage: string,
|
||||
ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext,
|
||||
): void {
|
||||
const command = this.commands[this.commands.length - 1];
|
||||
command.errors = command.errors || [];
|
||||
const stop = nonNullProp(ctx, 'stop');
|
||||
const currentErrorDesc: ErrorDescription = { message: errorMessage, range: new vscode.Range(ctx.start.line - 1, ctx.start.charPositionInLine, stop.line - 1, stop.charPositionInLine) };
|
||||
const currentErrorDesc: ErrorDescription = {
|
||||
message: errorMessage,
|
||||
range: new vscode.Range(
|
||||
ctx.start.line - 1,
|
||||
ctx.start.charPositionInLine,
|
||||
stop.line - 1,
|
||||
stop.charPositionInLine,
|
||||
),
|
||||
};
|
||||
command.errors.push(currentErrorDesc);
|
||||
}
|
||||
|
||||
|
@ -485,5 +593,4 @@ class FindMongoCommandsVisitor extends MongoVisitor<MongoCommand[]> {
|
|||
*/
|
||||
return argAsString.replace(removeDuplicatedBackslash, `\\\\$1`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,33 +11,45 @@ import { randomUtils } from '../utils/randomUtils';
|
|||
import { getBatchSizeSetting } from '../utils/workspacUtils';
|
||||
import { wrapError } from '../utils/wrapError';
|
||||
|
||||
const timeoutMessage = "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting.";
|
||||
const timeoutMessage =
|
||||
"Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting.";
|
||||
|
||||
const mongoShellMoreMessage = 'Type "it" for more';
|
||||
const extensionMoreMessage = '(More)';
|
||||
|
||||
const sentinelBase = 'EXECUTION COMPLETED';
|
||||
const sentinelRegex = /\"?EXECUTION COMPLETED [0-9a-fA-F]{10}\"?/;
|
||||
function createSentinel(): string { return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; }
|
||||
const sentinelRegex = /"?EXECUTION COMPLETED [0-9a-fA-F]{10}"?/;
|
||||
function createSentinel(): string {
|
||||
return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`;
|
||||
}
|
||||
|
||||
export class MongoShell extends vscode.Disposable {
|
||||
|
||||
constructor(private _process: InteractiveChildProcess, private _timeoutSeconds: number) {
|
||||
constructor(
|
||||
private _process: InteractiveChildProcess,
|
||||
private _timeoutSeconds: number,
|
||||
) {
|
||||
super(() => this.dispose());
|
||||
}
|
||||
|
||||
public static async create(execPath: string, execArgs: string[], connectionString: string, isEmulator: boolean | undefined, outputChannel: vscode.OutputChannel, timeoutSeconds: number): Promise<MongoShell> {
|
||||
public static async create(
|
||||
execPath: string,
|
||||
execArgs: string[],
|
||||
connectionString: string,
|
||||
isEmulator: boolean | undefined,
|
||||
outputChannel: vscode.OutputChannel,
|
||||
timeoutSeconds: number,
|
||||
): Promise<MongoShell> {
|
||||
try {
|
||||
const args: string[] = execArgs.slice() || []; // Snapshot since we modify it
|
||||
args.push(connectionString);
|
||||
|
||||
if (isEmulator) {
|
||||
// Without these the connection will fail due to the self-signed DocDB certificate
|
||||
if (args.indexOf("--ssl") < 0) {
|
||||
args.push("--ssl");
|
||||
if (args.indexOf('--ssl') < 0) {
|
||||
args.push('--ssl');
|
||||
}
|
||||
if (args.indexOf("--sslAllowInvalidCertificates") < 0) {
|
||||
args.push("--sslAllowInvalidCertificates");
|
||||
if (args.indexOf('--sslAllowInvalidCertificates') < 0) {
|
||||
args.push('--sslAllowInvalidCertificates');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,13 +58,13 @@ export class MongoShell extends vscode.Disposable {
|
|||
command: execPath,
|
||||
args,
|
||||
outputFilterSearch: sentinelRegex,
|
||||
outputFilterReplace: ''
|
||||
outputFilterReplace: '',
|
||||
});
|
||||
const shell: MongoShell = new MongoShell(process, timeoutSeconds);
|
||||
|
||||
// Try writing an empty script to verify the process is running correctly and allow us
|
||||
// to catch any errors related to the start-up of the process before trying to write to it.
|
||||
await shell.executeScript("");
|
||||
await shell.executeScript('');
|
||||
|
||||
// Configure the batch size
|
||||
await shell.executeScript(`DBQuery.shellBatchSize = ${getBatchSizeSetting()}`);
|
||||
|
@ -74,7 +86,7 @@ export class MongoShell extends vscode.Disposable {
|
|||
public async executeScript(script: string): Promise<string> {
|
||||
script = convertToSingleLine(script);
|
||||
|
||||
let stdOut = "";
|
||||
let stdOut = '';
|
||||
const sentinel = createSentinel();
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
@ -86,7 +98,7 @@ export class MongoShell extends vscode.Disposable {
|
|||
|
||||
// Hook up events
|
||||
disposables.push(
|
||||
this._process.onStdOut(text => {
|
||||
this._process.onStdOut((text) => {
|
||||
stdOut += text;
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel);
|
||||
|
@ -97,22 +109,30 @@ export class MongoShell extends vscode.Disposable {
|
|||
// since we're not currently interactive like that.
|
||||
// CONSIDER: Ideally we would allow users to click a button to iterate through more data,
|
||||
// or even just do it for them
|
||||
stdOutNoSentinel = stdOutNoSentinel.replace(mongoShellMoreMessage, extensionMoreMessage);
|
||||
stdOutNoSentinel = stdOutNoSentinel.replace(
|
||||
mongoShellMoreMessage,
|
||||
extensionMoreMessage,
|
||||
);
|
||||
|
||||
resolve(stdOutNoSentinel);
|
||||
}
|
||||
}));
|
||||
}),
|
||||
);
|
||||
disposables.push(
|
||||
this._process.onStdErr(text => {
|
||||
this._process.onStdErr((text) => {
|
||||
// Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT.
|
||||
// So consider this an error.
|
||||
// (It's okay if we fire this multiple times, the first one wins.)
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
||||
reject(wrapCheckOutputWindow(text.trim()));
|
||||
}));
|
||||
}),
|
||||
);
|
||||
disposables.push(
|
||||
this._process.onError(error => {
|
||||
this._process.onError((error) => {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
||||
reject(error);
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
||||
// Write the script to STDIN
|
||||
if (script) {
|
||||
|
@ -123,7 +143,6 @@ export class MongoShell extends vscode.Disposable {
|
|||
// it back out as a string value after it's done processing the script
|
||||
const quotedSentinel = `"${sentinel}"`;
|
||||
this._process.writeLine(quotedSentinel); // (Don't display the sentinel)
|
||||
|
||||
} catch (error) {
|
||||
// new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it
|
||||
|
||||
|
@ -131,16 +150,16 @@ export class MongoShell extends vscode.Disposable {
|
|||
// Give a chance for start-up errors to show up before rejecting with this more general error message
|
||||
await delay(500);
|
||||
// eslint-disable-next-line no-ex-assign
|
||||
error = new Error("The process exited prematurely.");
|
||||
error = new Error('The process exited prematurely.');
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
||||
reject(wrapCheckOutputWindow(error));
|
||||
}
|
||||
});
|
||||
|
||||
return result.trim();
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
// Dispose event handlers
|
||||
for (const d of disposables) {
|
||||
d.dispose();
|
||||
|
@ -149,21 +168,19 @@ export class MongoShell extends vscode.Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
function startScriptTimeout(timeoutSeconds: number | 0, reject: (err: unknown) => void): void {
|
||||
function startScriptTimeout(timeoutSeconds: number, reject: (err: unknown) => void): void {
|
||||
if (timeoutSeconds > 0) {
|
||||
setTimeout(
|
||||
() => {
|
||||
reject(timeoutMessage);
|
||||
},
|
||||
timeoutSeconds * 1000);
|
||||
setTimeout(() => {
|
||||
reject(timeoutMessage);
|
||||
}, timeoutSeconds * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function convertToSingleLine(script: string): string {
|
||||
return script.split(os.EOL)
|
||||
.map(line => line.trim())
|
||||
return script
|
||||
.split(os.EOL)
|
||||
.map((line) => line.trim())
|
||||
.join('');
|
||||
|
||||
}
|
||||
|
||||
function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } {
|
||||
|
@ -176,12 +193,12 @@ function removeSentinel(text: string, sentinel: string): { text: string; removed
|
|||
}
|
||||
|
||||
async function delay(milliseconds: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, milliseconds);
|
||||
});
|
||||
}
|
||||
|
||||
function wrapCheckOutputWindow(error: unknown): unknown {
|
||||
const checkOutputMsg = "The output window may contain additional information.";
|
||||
const checkOutputMsg = 'The output window may contain additional information.';
|
||||
return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg);
|
||||
}
|
||||
|
|
|
@ -3,14 +3,19 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, IActionContext, ITreeItemPickerContext, callWithTelemetryAndErrorHandling } from "@microsoft/vscode-azext-utils";
|
||||
import { Experience, MongoExperience } from "../../AzureDBExperiences";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { setConnectedNode } from "../setConnectedNode";
|
||||
import { MongoDatabaseTreeItem } from "../tree/MongoDatabaseTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
type AzExtTreeItem,
|
||||
type IActionContext,
|
||||
type ITreeItemPickerContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import { MongoExperience, type Experience } from '../../AzureDBExperiences';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { setConnectedNode } from '../setConnectedNode';
|
||||
import { MongoDatabaseTreeItem } from '../tree/MongoDatabaseTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export const connectedMongoKey: string = "ms-azuretools.vscode-cosmosdb.connectedDB";
|
||||
export const connectedMongoKey: string = 'ms-azuretools.vscode-cosmosdb.connectedDB';
|
||||
|
||||
export async function loadPersistedMongoDB(): Promise<void> {
|
||||
return callWithTelemetryAndErrorHandling('cosmosDB.loadPersistedMongoDB', async (context: IActionContext) => {
|
||||
|
@ -38,7 +43,10 @@ export async function loadPersistedMongoDB(): Promise<void> {
|
|||
export async function connectMongoDatabase(context: IActionContext, node?: MongoDatabaseTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
// Include defaultExperience in the context to prevent https://github.com/microsoft/vscode-cosmosdb/issues/1517
|
||||
const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = { ...context, defaultExperience: MongoExperience };
|
||||
const experienceContext: ITreeItemPickerContext & { defaultExperience?: Experience } = {
|
||||
...context,
|
||||
defaultExperience: MongoExperience,
|
||||
};
|
||||
node = await pickMongo<MongoDatabaseTreeItem>(experienceContext, MongoDatabaseTreeItem.contextValue);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { MongoDatabaseTreeItem } from "../tree/MongoDatabaseTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { MongoDatabaseTreeItem } from '../tree/MongoDatabaseTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function createMongoCollection(context: IActionContext, node?: MongoDatabaseTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { MongoAccountTreeItem } from "../tree/MongoAccountTreeItem";
|
||||
import { MongoDatabaseTreeItem } from "../tree/MongoDatabaseTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { type MongoAccountTreeItem } from '../tree/MongoAccountTreeItem';
|
||||
import { type MongoDatabaseTreeItem } from '../tree/MongoDatabaseTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function createMongoDatabase(context: IActionContext, node?: MongoAccountTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { MongoCollectionTreeItem } from "../tree/MongoCollectionTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { MongoCollectionTreeItem } from '../tree/MongoCollectionTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function createMongoDocument(context: IActionContext, node?: MongoCollectionTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
node = await pickMongo<MongoCollectionTreeItem>(context, MongoCollectionTreeItem.contextValue);
|
||||
}
|
||||
const documentNode = await node.createChild(context);
|
||||
await vscode.commands.executeCommand("cosmosDB.openDocument", documentNode);
|
||||
await vscode.commands.executeCommand('cosmosDB.openDocument', documentNode);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscodeUtil from "../../utils/vscodeUtils";
|
||||
import * as vscodeUtil from '../../utils/vscodeUtils';
|
||||
|
||||
export async function createMongoSrapbook(): Promise<void> {
|
||||
await vscodeUtil.showNewFile('', 'Scrapbook', '.mongo');
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { MongoCollectionTreeItem } from "../tree/MongoCollectionTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { MongoCollectionTreeItem } from '../tree/MongoCollectionTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function deleteMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { localize } from "../../utils/localize";
|
||||
import { setConnectedNode } from "../setConnectedNode";
|
||||
import { MongoDatabaseTreeItem } from "../tree/MongoDatabaseTreeItem";
|
||||
import { connectedMongoKey } from "./connectMongoDatabase";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { localize } from '../../utils/localize';
|
||||
import { setConnectedNode } from '../setConnectedNode';
|
||||
import { MongoDatabaseTreeItem } from '../tree/MongoDatabaseTreeItem';
|
||||
import { connectedMongoKey } from './connectMongoDatabase';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function deleteMongoDB(context: IActionContext, node?: MongoDatabaseTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
@ -25,7 +25,7 @@ export async function deleteMongoDB(context: IActionContext, node?: MongoDatabas
|
|||
// Temporary workaround for https://github.com/microsoft/vscode-cosmosdb/issues/1754
|
||||
void ext.mongoLanguageClient.disconnect();
|
||||
}
|
||||
const successMessage = localize("deleteMongoDatabaseMsg", 'Successfully deleted database "{0}"', node.databaseName);
|
||||
const successMessage = localize('deleteMongoDatabaseMsg', 'Successfully deleted database "{0}"', node.databaseName);
|
||||
void vscode.window.showInformationMessage(successMessage);
|
||||
ext.outputChannel.info(successMessage);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext, ITreeItemPickerContext } from "@microsoft/vscode-azext-utils";
|
||||
import { MongoDocumentTreeItem } from "../tree/MongoDocumentTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext, type ITreeItemPickerContext } from '@microsoft/vscode-azext-utils';
|
||||
import { MongoDocumentTreeItem } from '../tree/MongoDocumentTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function deleteMongoDocument(context: IActionContext, node?: MongoDocumentTreeItem): Promise<void> {
|
||||
const suppressCreateContext: ITreeItemPickerContext = context;
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { executeAllCommandsFromActiveEditor } from "../MongoScrapbook";
|
||||
import { loadPersistedMongoDB } from "./connectMongoDatabase";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { executeAllCommandsFromActiveEditor } from '../MongoScrapbook';
|
||||
import { loadPersistedMongoDB } from './connectMongoDatabase';
|
||||
|
||||
export async function executeAllMongoCommand(context: IActionContext): Promise<void> {
|
||||
await loadPersistedMongoDB();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { executeCommandFromActiveEditor } from "../MongoScrapbook";
|
||||
import { loadPersistedMongoDB } from "./connectMongoDatabase";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import type * as vscode from 'vscode';
|
||||
import { executeCommandFromActiveEditor } from '../MongoScrapbook';
|
||||
import { loadPersistedMongoDB } from './connectMongoDatabase';
|
||||
|
||||
export async function executeMongoCommand(context: IActionContext, position?: vscode.Position): Promise<void> {
|
||||
await loadPersistedMongoDB();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function launchMongoShell(): void {
|
||||
const terminal: vscode.Terminal = vscode.window.createTerminal('Mongo Shell');
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { MongoCollectionTreeItem } from "../tree/MongoCollectionTreeItem";
|
||||
import { pickMongo } from "./pickMongo";
|
||||
import { type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { ext } from '../../extensionVariables';
|
||||
import { MongoCollectionTreeItem } from '../tree/MongoCollectionTreeItem';
|
||||
import { pickMongo } from './pickMongo';
|
||||
|
||||
export async function openMongoCollection(context: IActionContext, node?: MongoCollectionTreeItem): Promise<void> {
|
||||
if (!node) {
|
||||
|
|
|
@ -3,18 +3,16 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AzExtTreeItem, IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import { cosmosMongoFilter } from "../../constants";
|
||||
import { ext } from "../../extensionVariables";
|
||||
import { type AzExtTreeItem, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import { cosmosMongoFilter } from '../../constants';
|
||||
import { ext } from '../../extensionVariables';
|
||||
|
||||
export async function pickMongo<T extends AzExtTreeItem>(
|
||||
context: IActionContext,
|
||||
expectedContextValue?: string | RegExp | (string | RegExp)[]
|
||||
expectedContextValue?: string | RegExp | (string | RegExp)[],
|
||||
): Promise<T> {
|
||||
return await ext.rgApi.pickAppResource<T>(context, {
|
||||
filter: [
|
||||
cosmosMongoFilter
|
||||
],
|
||||
expectedChildContextValue: expectedContextValue
|
||||
filter: [cosmosMongoFilter],
|
||||
expectedChildContextValue: expectedContextValue,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MongoClient, MongoClientOptions } from 'mongodb';
|
||||
import { MongoClient, type MongoClientOptions } from 'mongodb';
|
||||
import { emulatorPassword, Links } from '../constants';
|
||||
|
||||
export async function connectToMongoClient(connectionString: string, appName: string): Promise<MongoClient> {
|
||||
|
@ -13,7 +13,7 @@ export async function connectToMongoClient(connectionString: string, appName: st
|
|||
appName: `@${appName}@`,
|
||||
// https://github.com/lmammino/mongo-uri-builder/issues/2
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true
|
||||
useUnifiedTopology: true,
|
||||
};
|
||||
|
||||
if (isCosmosEmulatorConnectionString(connectionString)) {
|
||||
|
@ -25,7 +25,7 @@ export async function connectToMongoClient(connectionString: string, appName: st
|
|||
return await MongoClient.connect(connectionString, options);
|
||||
} catch (err) {
|
||||
// Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info
|
||||
const error = <{ message?: string, name?: string }>err;
|
||||
const error = <{ message?: string; name?: string }>err;
|
||||
const message = error && error.message;
|
||||
|
||||
// Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]"
|
||||
|
@ -34,13 +34,16 @@ export async function connectToMongoClient(connectionString: string, appName: st
|
|||
throw new MongoConnectError();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export class MongoConnectError extends Error {
|
||||
constructor() {
|
||||
super(`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`);
|
||||
super(
|
||||
`Unable to connect to local Mongo DB instance. Make sure it is started correctly. See ${Links.LocalConnectionDebuggingTips} for tips.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener';
|
||||
import { RecognitionException } from 'antlr4ts/RecognitionException';
|
||||
import { Recognizer } from 'antlr4ts/Recognizer';
|
||||
import { Token } from 'antlr4ts/Token';
|
||||
import * as vscode from "vscode";
|
||||
import { ErrorDescription } from './MongoCommand';
|
||||
import { type ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener';
|
||||
import { type RecognitionException } from 'antlr4ts/RecognitionException';
|
||||
import { type Recognizer } from 'antlr4ts/Recognizer';
|
||||
import { type Token } from 'antlr4ts/Token';
|
||||
import * as vscode from 'vscode';
|
||||
import { type ErrorDescription } from './MongoCommand';
|
||||
|
||||
export class ParserErrorListener implements ANTLRErrorListener<Token> {
|
||||
private _errors: ErrorDescription[] = [];
|
||||
|
@ -24,15 +24,15 @@ export class ParserErrorListener implements ANTLRErrorListener<Token> {
|
|||
line: number,
|
||||
charPositionInLine: number,
|
||||
msg: string,
|
||||
e: RecognitionException | undefined): void {
|
||||
|
||||
e: RecognitionException | undefined,
|
||||
): void {
|
||||
const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed
|
||||
const range = new vscode.Range(position, position);
|
||||
|
||||
const error: ErrorDescription = {
|
||||
message: msg,
|
||||
range: range,
|
||||
exception: e
|
||||
exception: e,
|
||||
};
|
||||
this._errors.push(error);
|
||||
}
|
||||
|
@ -52,15 +52,15 @@ export class LexerErrorListener implements ANTLRErrorListener<number> {
|
|||
line: number,
|
||||
charPositionInLine: number,
|
||||
msg: string,
|
||||
e: RecognitionException | undefined): void {
|
||||
|
||||
e: RecognitionException | undefined,
|
||||
): void {
|
||||
const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed
|
||||
const range = new vscode.Range(position, position);
|
||||
|
||||
const error: ErrorDescription = {
|
||||
message: msg,
|
||||
range: range,
|
||||
exception: e
|
||||
exception: e,
|
||||
};
|
||||
this._errors.push(error);
|
||||
}
|
||||
|
|
|
@ -9,19 +9,17 @@
|
|||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-nocheck
|
||||
|
||||
import { ATN } from 'antlr4ts/atn/ATN';
|
||||
import { type ATN } from 'antlr4ts/atn/ATN';
|
||||
import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer';
|
||||
import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator';
|
||||
import { CharStream } from 'antlr4ts/CharStream';
|
||||
import { type CharStream } from 'antlr4ts/CharStream';
|
||||
import { NotNull, Override } from 'antlr4ts/Decorators';
|
||||
import { Lexer } from 'antlr4ts/Lexer';
|
||||
import * as Utils from 'antlr4ts/misc/Utils';
|
||||
import { RuleContext } from 'antlr4ts/RuleContext';
|
||||
import { Vocabulary } from 'antlr4ts/Vocabulary';
|
||||
import { type RuleContext } from 'antlr4ts/RuleContext';
|
||||
import { type Vocabulary } from 'antlr4ts/Vocabulary';
|
||||
import { VocabularyImpl } from 'antlr4ts/VocabularyImpl';
|
||||
|
||||
|
||||
|
||||
export class mongoLexer extends Lexer {
|
||||
public static readonly T__0 = 1;
|
||||
public static readonly T__1 = 2;
|
||||
|
@ -47,32 +45,95 @@ export class mongoLexer extends Lexer {
|
|||
public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22;
|
||||
public static readonly SINGLE_QUOTED_STRING_LITERAL = 23;
|
||||
public static readonly WHITESPACE = 24;
|
||||
public static readonly modeNames: string[] = [
|
||||
"DEFAULT_MODE"
|
||||
];
|
||||
public static readonly modeNames: string[] = ['DEFAULT_MODE'];
|
||||
|
||||
public static readonly ruleNames: string[] = [
|
||||
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "RegexLiteral",
|
||||
"RegexFlag", "SingleLineComment", "MultiLineComment", "StringLiteral",
|
||||
"NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral", "LineTerminator",
|
||||
"SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL",
|
||||
"SINGLE_QUOTED_STRING_LITERAL", "STRING_ESCAPE", "DecimalIntegerLiteral",
|
||||
"ExponentPart", "DecimalDigit", "WHITESPACE"
|
||||
'T__0',
|
||||
'T__1',
|
||||
'T__2',
|
||||
'T__3',
|
||||
'T__4',
|
||||
'T__5',
|
||||
'T__6',
|
||||
'T__7',
|
||||
'RegexLiteral',
|
||||
'RegexFlag',
|
||||
'SingleLineComment',
|
||||
'MultiLineComment',
|
||||
'StringLiteral',
|
||||
'NullLiteral',
|
||||
'BooleanLiteral',
|
||||
'NumericLiteral',
|
||||
'DecimalLiteral',
|
||||
'LineTerminator',
|
||||
'SEMICOLON',
|
||||
'DOT',
|
||||
'DB',
|
||||
'IDENTIFIER',
|
||||
'DOUBLE_QUOTED_STRING_LITERAL',
|
||||
'SINGLE_QUOTED_STRING_LITERAL',
|
||||
'STRING_ESCAPE',
|
||||
'DecimalIntegerLiteral',
|
||||
'ExponentPart',
|
||||
'DecimalDigit',
|
||||
'WHITESPACE',
|
||||
];
|
||||
|
||||
private static readonly _LITERAL_NAMES: (string | undefined)[] = [
|
||||
undefined, "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "':'", undefined,
|
||||
undefined, undefined, undefined, "'null'", undefined, undefined, undefined,
|
||||
undefined, "';'", "'.'", "'db'"
|
||||
undefined,
|
||||
"'('",
|
||||
"','",
|
||||
"')'",
|
||||
"'{'",
|
||||
"'}'",
|
||||
"'['",
|
||||
"']'",
|
||||
"':'",
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
"'null'",
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
"';'",
|
||||
"'.'",
|
||||
"'db'",
|
||||
];
|
||||
private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [
|
||||
undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
||||
undefined, undefined, "RegexLiteral", "SingleLineComment", "MultiLineComment",
|
||||
"StringLiteral", "NullLiteral", "BooleanLiteral", "NumericLiteral", "DecimalLiteral",
|
||||
"LineTerminator", "SEMICOLON", "DOT", "DB", "IDENTIFIER", "DOUBLE_QUOTED_STRING_LITERAL",
|
||||
"SINGLE_QUOTED_STRING_LITERAL", "WHITESPACE"
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'RegexLiteral',
|
||||
'SingleLineComment',
|
||||
'MultiLineComment',
|
||||
'StringLiteral',
|
||||
'NullLiteral',
|
||||
'BooleanLiteral',
|
||||
'NumericLiteral',
|
||||
'DecimalLiteral',
|
||||
'LineTerminator',
|
||||
'SEMICOLON',
|
||||
'DOT',
|
||||
'DB',
|
||||
'IDENTIFIER',
|
||||
'DOUBLE_QUOTED_STRING_LITERAL',
|
||||
'SINGLE_QUOTED_STRING_LITERAL',
|
||||
'WHITESPACE',
|
||||
];
|
||||
public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(mongoLexer._LITERAL_NAMES, mongoLexer._SYMBOLIC_NAMES, []);
|
||||
public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(
|
||||
mongoLexer._LITERAL_NAMES,
|
||||
mongoLexer._SYMBOLIC_NAMES,
|
||||
[],
|
||||
);
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
|
@ -80,28 +141,34 @@ export class mongoLexer extends Lexer {
|
|||
return mongoLexer.VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
private isExternalIdentifierText(text) {
|
||||
return text === 'db';
|
||||
}
|
||||
|
||||
|
||||
constructor(input: CharStream) {
|
||||
super(input);
|
||||
this._interp = new LexerATNSimulator(mongoLexer._ATN, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public get grammarFileName(): string { return "mongo.g4"; }
|
||||
public get grammarFileName(): string {
|
||||
return 'mongo.g4';
|
||||
}
|
||||
|
||||
@Override
|
||||
public get ruleNames(): string[] { return mongoLexer.ruleNames; }
|
||||
public get ruleNames(): string[] {
|
||||
return mongoLexer.ruleNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public get serializedATN(): string { return mongoLexer._serializedATN; }
|
||||
public get serializedATN(): string {
|
||||
return mongoLexer._serializedATN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public get modeNames(): string[] { return mongoLexer.modeNames; }
|
||||
public get modeNames(): string[] {
|
||||
return mongoLexer.modeNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean {
|
||||
|
@ -114,126 +181,125 @@ export class mongoLexer extends Lexer {
|
|||
private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean {
|
||||
switch (predIndex) {
|
||||
case 0:
|
||||
return !this.isExternalIdentifierText(this.text)
|
||||
;
|
||||
return !this.isExternalIdentifierText(this.text);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static readonly _serializedATN: string =
|
||||
"\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01" +
|
||||
"\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" +
|
||||
"\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" +
|
||||
"\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" +
|
||||
"\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" +
|
||||
"\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" +
|
||||
"\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04" +
|
||||
"\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03" +
|
||||
"\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n" +
|
||||
"\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03" +
|
||||
"\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r" +
|
||||
"\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" +
|
||||
"\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F" +
|
||||
"\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" +
|
||||
"\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03" +
|
||||
"\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n" +
|
||||
"\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12" +
|
||||
"\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13" +
|
||||
"\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16" +
|
||||
"\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03" +
|
||||
"\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18" +
|
||||
"\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19" +
|
||||
"\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" +
|
||||
"\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C" +
|
||||
"\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA" +
|
||||
"\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03" +
|
||||
"\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" +
|
||||
"\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02" +
|
||||
"\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13\'\x02\x14)\x02\x15+\x02\x16" +
|
||||
"-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A" +
|
||||
"\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik" +
|
||||
"kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F\"\"$$)+.0<=" +
|
||||
"]_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G" +
|
||||
"Ggg\x04\x02--//\x03\x022;\x04\x02\v\v\"\"\u0106\x02\x03\x03\x02\x02\x02" +
|
||||
"\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02" +
|
||||
"\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02" +
|
||||
"\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02" +
|
||||
"\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02" +
|
||||
"\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03" +
|
||||
"\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" +
|
||||
"\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02" +
|
||||
";\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02" +
|
||||
"\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F" +
|
||||
"I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02" +
|
||||
"\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02" +
|
||||
"\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02" +
|
||||
"\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02\'\xB3\x03\x02\x02\x02)" +
|
||||
"\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03" +
|
||||
"\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02" +
|
||||
"\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>" +
|
||||
"\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02" +
|
||||
"AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E" +
|
||||
"F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02" +
|
||||
"IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02" +
|
||||
"MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02" +
|
||||
"\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02" +
|
||||
"\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02" +
|
||||
"\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02" +
|
||||
"\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02" +
|
||||
"\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02" +
|
||||
"\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02" +
|
||||
"\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02" +
|
||||
"\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02" +
|
||||
"\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02" +
|
||||
"qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02" +
|
||||
"uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02" +
|
||||
"xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03" +
|
||||
"\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02" +
|
||||
"\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82" +
|
||||
"\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03" +
|
||||
"\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02" +
|
||||
"\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C" +
|
||||
"\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03" +
|
||||
"\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07" +
|
||||
"/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03" +
|
||||
"\x02\x02\x02\x94\x95\x05#\x12\x02\x95\"\x03\x02\x02\x02\x96\x97\x055\x1B" +
|
||||
"\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02" +
|
||||
"\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02" +
|
||||
"\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02" +
|
||||
"\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02" +
|
||||
"\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02" +
|
||||
"\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02" +
|
||||
"\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02" +
|
||||
"\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB" +
|
||||
"\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD" +
|
||||
"\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE" +
|
||||
"$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2" +
|
||||
"\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02" +
|
||||
"\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02" +
|
||||
"\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD" +
|
||||
"\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE" +
|
||||
"\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0" +
|
||||
"\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7" +
|
||||
"\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02" +
|
||||
"\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02" +
|
||||
"\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02" +
|
||||
"\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02" +
|
||||
"\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF" +
|
||||
"\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1" +
|
||||
"\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4" +
|
||||
"\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t" +
|
||||
"\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02" +
|
||||
"\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02" +
|
||||
"\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02" +
|
||||
"\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02" +
|
||||
"\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4" +
|
||||
"\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9" +
|
||||
"\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8" +
|
||||
"\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED" +
|
||||
"\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02" +
|
||||
"\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F" +
|
||||
"\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA" +
|
||||
"\x04\x02\x03\x02\b\x02\x02";
|
||||
'\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01' +
|
||||
'\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06' +
|
||||
'\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r' +
|
||||
'\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t' +
|
||||
'\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t' +
|
||||
'\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t' +
|
||||
'\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04' +
|
||||
'\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03' +
|
||||
'\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n' +
|
||||
'\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03' +
|
||||
'\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r' +
|
||||
'\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03' +
|
||||
'\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F' +
|
||||
'\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10' +
|
||||
'\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03' +
|
||||
'\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n' +
|
||||
'\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12' +
|
||||
'\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13' +
|
||||
'\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16' +
|
||||
'\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03' +
|
||||
'\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18' +
|
||||
'\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19' +
|
||||
'\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03' +
|
||||
'\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C' +
|
||||
'\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA' +
|
||||
'\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03' +
|
||||
'\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t' +
|
||||
'\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02' +
|
||||
"\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" +
|
||||
'-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A' +
|
||||
'\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik' +
|
||||
'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' +
|
||||
']_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G' +
|
||||
'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' +
|
||||
'\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02' +
|
||||
'\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02' +
|
||||
'\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02' +
|
||||
'\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02' +
|
||||
'\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03' +
|
||||
"\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" +
|
||||
'\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02' +
|
||||
';\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02' +
|
||||
'\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F' +
|
||||
'I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02' +
|
||||
'\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02' +
|
||||
'\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02' +
|
||||
"\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" +
|
||||
'\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03' +
|
||||
'\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02' +
|
||||
'\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>' +
|
||||
'\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02' +
|
||||
'AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E' +
|
||||
'F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02' +
|
||||
'IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02' +
|
||||
'MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02' +
|
||||
'\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02' +
|
||||
'\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02' +
|
||||
'\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02' +
|
||||
'\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02' +
|
||||
'\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02' +
|
||||
'\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02' +
|
||||
'\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02' +
|
||||
'\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02' +
|
||||
'\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02' +
|
||||
'qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02' +
|
||||
'uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02' +
|
||||
'xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03' +
|
||||
'\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02' +
|
||||
'\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82' +
|
||||
'\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03' +
|
||||
'\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02' +
|
||||
'\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C' +
|
||||
'\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03' +
|
||||
'\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07' +
|
||||
'/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03' +
|
||||
'\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' +
|
||||
'\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02' +
|
||||
'\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02' +
|
||||
'\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02' +
|
||||
'\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02' +
|
||||
'\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02' +
|
||||
'\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02' +
|
||||
'\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02' +
|
||||
'\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB' +
|
||||
'\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD' +
|
||||
'\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE' +
|
||||
'$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2' +
|
||||
'\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02' +
|
||||
'\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02' +
|
||||
'\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD' +
|
||||
'\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE' +
|
||||
'\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0' +
|
||||
'\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7' +
|
||||
'\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02' +
|
||||
'\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02' +
|
||||
'\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02' +
|
||||
'\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02' +
|
||||
'\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF' +
|
||||
'\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1' +
|
||||
'\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4' +
|
||||
'\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t' +
|
||||
'\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02' +
|
||||
'\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02' +
|
||||
'\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02' +
|
||||
'\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02' +
|
||||
'\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4' +
|
||||
'\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9' +
|
||||
'\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8' +
|
||||
'\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED' +
|
||||
'\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02' +
|
||||
'\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F' +
|
||||
'\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA' +
|
||||
'\x04\x02\x03\x02\b\x02\x02';
|
||||
public static __ATN: ATN;
|
||||
public static get _ATN(): ATN {
|
||||
if (!mongoLexer.__ATN) {
|
||||
|
@ -242,6 +308,4 @@ export class mongoLexer extends Lexer {
|
|||
|
||||
return mongoLexer.__ATN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,208 +1,220 @@
|
|||
// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener';
|
||||
import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser';
|
||||
|
||||
|
||||
import { type ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener';
|
||||
import {
|
||||
type ArgumentContext,
|
||||
type ArgumentsContext,
|
||||
type ArrayLiteralContext,
|
||||
type CollectionContext,
|
||||
type CommandContext,
|
||||
type CommandsContext,
|
||||
type CommentContext,
|
||||
type ElementListContext,
|
||||
type EmptyCommandContext,
|
||||
type FunctionCallContext,
|
||||
type LiteralContext,
|
||||
type MongoCommandsContext,
|
||||
type ObjectLiteralContext,
|
||||
type PropertyAssignmentContext,
|
||||
type PropertyNameAndValueListContext,
|
||||
type PropertyNameContext,
|
||||
type PropertyValueContext,
|
||||
} from './mongoParser';
|
||||
|
||||
/**
|
||||
* This interface defines a complete listener for a parse tree produced by
|
||||
* `mongoParser`.
|
||||
*/
|
||||
export interface mongoListener extends ParseTreeListener {
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterMongoCommands?: (ctx: MongoCommandsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitMongoCommands?: (ctx: MongoCommandsContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterMongoCommands?: (ctx: MongoCommandsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitMongoCommands?: (ctx: MongoCommandsContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCommands?: (ctx: CommandsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCommands?: (ctx: CommandsContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCommands?: (ctx: CommandsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCommands?: (ctx: CommandsContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCommand?: (ctx: CommandContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCommand?: (ctx: CommandContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCommand?: (ctx: CommandContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCommand?: (ctx: CommandContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterEmptyCommand?: (ctx: EmptyCommandContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitEmptyCommand?: (ctx: EmptyCommandContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterEmptyCommand?: (ctx: EmptyCommandContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitEmptyCommand?: (ctx: EmptyCommandContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCollection?: (ctx: CollectionContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCollection?: (ctx: CollectionContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterCollection?: (ctx: CollectionContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitCollection?: (ctx: CollectionContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterFunctionCall?: (ctx: FunctionCallContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitFunctionCall?: (ctx: FunctionCallContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterFunctionCall?: (ctx: FunctionCallContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitFunctionCall?: (ctx: FunctionCallContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArguments?: (ctx: ArgumentsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArguments?: (ctx: ArgumentsContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArguments?: (ctx: ArgumentsContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArguments?: (ctx: ArgumentsContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArgument?: (ctx: ArgumentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArgument?: (ctx: ArgumentContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArgument?: (ctx: ArgumentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArgument?: (ctx: ArgumentContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterObjectLiteral?: (ctx: ObjectLiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitObjectLiteral?: (ctx: ObjectLiteralContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterObjectLiteral?: (ctx: ObjectLiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitObjectLiteral?: (ctx: ObjectLiteralContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArrayLiteral?: (ctx: ArrayLiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArrayLiteral?: (ctx: ArrayLiteralContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterArrayLiteral?: (ctx: ArrayLiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitArrayLiteral?: (ctx: ArrayLiteralContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterElementList?: (ctx: ElementListContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitElementList?: (ctx: ElementListContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterElementList?: (ctx: ElementListContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitElementList?: (ctx: ElementListContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyValue?: (ctx: PropertyValueContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyValue?: (ctx: PropertyValueContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyValue?: (ctx: PropertyValueContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyValue?: (ctx: PropertyValueContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterLiteral?: (ctx: LiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitLiteral?: (ctx: LiteralContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterLiteral?: (ctx: LiteralContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitLiteral?: (ctx: LiteralContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyName?: (ctx: PropertyNameContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyName?: (ctx: PropertyNameContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterPropertyName?: (ctx: PropertyNameContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitPropertyName?: (ctx: PropertyNameContext) => void;
|
||||
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterComment?: (ctx: CommentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitComment?: (ctx: CommentContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterComment?: (ctx: CommentContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitComment?: (ctx: CommentContext) => void;
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,17 +1,30 @@
|
|||
// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
import { ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor';
|
||||
import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionContext, CommandContext, CommandsContext, CommentContext, ElementListContext, EmptyCommandContext, FunctionCallContext, LiteralContext, MongoCommandsContext, ObjectLiteralContext, PropertyAssignmentContext, PropertyNameAndValueListContext, PropertyNameContext, PropertyValueContext } from './mongoParser';
|
||||
|
||||
|
||||
import { type ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor';
|
||||
import {
|
||||
type ArgumentContext,
|
||||
type ArgumentsContext,
|
||||
type ArrayLiteralContext,
|
||||
type CollectionContext,
|
||||
type CommandContext,
|
||||
type CommandsContext,
|
||||
type CommentContext,
|
||||
type ElementListContext,
|
||||
type EmptyCommandContext,
|
||||
type FunctionCallContext,
|
||||
type LiteralContext,
|
||||
type MongoCommandsContext,
|
||||
type ObjectLiteralContext,
|
||||
type PropertyAssignmentContext,
|
||||
type PropertyNameAndValueListContext,
|
||||
type PropertyNameContext,
|
||||
type PropertyValueContext,
|
||||
} from './mongoParser';
|
||||
|
||||
/**
|
||||
* This interface defines a complete generic visitor for a parse tree produced
|
||||
|
@ -21,123 +34,122 @@ import { ArgumentContext, ArgumentsContext, ArrayLiteralContext, CollectionConte
|
|||
* operations with no return type.
|
||||
*/
|
||||
export interface mongoVisitor<Result> extends ParseTreeVisitor<Result> {
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitMongoCommands?: (ctx: MongoCommandsContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.mongoCommands`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitMongoCommands?: (ctx: MongoCommandsContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCommands?: (ctx: CommandsContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.commands`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCommands?: (ctx: CommandsContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCommand?: (ctx: CommandContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.command`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCommand?: (ctx: CommandContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitEmptyCommand?: (ctx: EmptyCommandContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.emptyCommand`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitEmptyCommand?: (ctx: EmptyCommandContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCollection?: (ctx: CollectionContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.collection`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitCollection?: (ctx: CollectionContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitFunctionCall?: (ctx: FunctionCallContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.functionCall`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitFunctionCall?: (ctx: FunctionCallContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArguments?: (ctx: ArgumentsContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.arguments`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArguments?: (ctx: ArgumentsContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArgument?: (ctx: ArgumentContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.argument`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArgument?: (ctx: ArgumentContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.objectLiteral`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.arrayLiteral`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitElementList?: (ctx: ElementListContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.elementList`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitElementList?: (ctx: ElementListContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyNameAndValueList`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyAssignment`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyValue?: (ctx: PropertyValueContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyValue`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyValue?: (ctx: PropertyValueContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitLiteral?: (ctx: LiteralContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.literal`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitLiteral?: (ctx: LiteralContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyName?: (ctx: PropertyNameContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.propertyName`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitPropertyName?: (ctx: PropertyNameContext) => Result;
|
||||
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitComment?: (ctx: CommentContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `mongoParser.comment`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitComment?: (ctx: CommentContext) => Result;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,22 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ParserRuleContext } from 'antlr4ts/ParserRuleContext';
|
||||
import { ErrorNode } from 'antlr4ts/tree/ErrorNode';
|
||||
import { ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
||||
import { ArgumentContext, ArgumentsContext, CollectionContext, CommandContext, CommandsContext, FunctionCallContext, MongoCommandsContext } from './mongoParser';
|
||||
import { mongoVisitor } from './mongoVisitor';
|
||||
import { type ParserRuleContext } from 'antlr4ts/ParserRuleContext';
|
||||
import { type ErrorNode } from 'antlr4ts/tree/ErrorNode';
|
||||
import { type ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { type TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
||||
import {
|
||||
type ArgumentContext,
|
||||
type ArgumentsContext,
|
||||
type CollectionContext,
|
||||
type CommandContext,
|
||||
type CommandsContext,
|
||||
type FunctionCallContext,
|
||||
type MongoCommandsContext,
|
||||
} from './mongoParser';
|
||||
import { type mongoVisitor } from './mongoVisitor';
|
||||
|
||||
export class MongoVisitor<T> implements mongoVisitor<T> {
|
||||
|
||||
visitMongoCommands(ctx: MongoCommandsContext): T {
|
||||
return this.visitChildren(ctx);
|
||||
}
|
||||
|
@ -46,7 +53,7 @@ export class MongoVisitor<T> implements mongoVisitor<T> {
|
|||
|
||||
visitChildren(ctx: ParserRuleContext): T {
|
||||
let result = this.defaultResult(ctx);
|
||||
const n = ctx.childCount
|
||||
const n = ctx.childCount;
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (!this.shouldVisitNextChild(ctx, result)) {
|
||||
break;
|
||||
|
@ -69,7 +76,7 @@ export class MongoVisitor<T> implements mongoVisitor<T> {
|
|||
|
||||
protected defaultResult(_node: ParseTree): T {
|
||||
// grandfathered-in. Unclear why this is null instead of type T
|
||||
return <T><unknown>null;
|
||||
return <T>(<unknown>null);
|
||||
}
|
||||
|
||||
protected aggregateResult(aggregate: T, nextResult: T): T {
|
||||
|
|
|
@ -4,22 +4,21 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils';
|
||||
import * as path from 'path';
|
||||
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
|
||||
import { LanguageClient, TransportKind, type LanguageClientOptions, type ServerOptions } from 'vscode-languageclient';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { ext } from '../extensionVariables';
|
||||
import { IConnectionParams } from './services/IConnectionParams';
|
||||
import { type IConnectionParams } from './services/IConnectionParams';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class MongoDBLanguageClient {
|
||||
|
||||
public client: LanguageClient;
|
||||
|
||||
constructor() {
|
||||
// The server is implemented in node
|
||||
const serverModule = ext.ignoreBundle ?
|
||||
ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js')) :
|
||||
ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js'));
|
||||
const serverModule = ext.ignoreBundle
|
||||
? ext.context.asAbsolutePath(path.join('out', 'src', 'mongo', 'languageServer.js'))
|
||||
: ext.context.asAbsolutePath(path.join('dist', 'mongo-languageServer.bundle.js'));
|
||||
// The debug options for the server
|
||||
const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] };
|
||||
|
||||
|
@ -27,7 +26,7 @@ export class MongoDBLanguageClient {
|
|||
// Otherwise the run options are used
|
||||
const serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
|
||||
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions },
|
||||
};
|
||||
|
||||
// Options to control the language client
|
||||
|
@ -35,12 +34,17 @@ export class MongoDBLanguageClient {
|
|||
// Register the server for mongo javascript documents
|
||||
documentSelector: [
|
||||
{ language: 'mongo', scheme: 'file' },
|
||||
{ language: 'mongo', scheme: 'untitled' }
|
||||
]
|
||||
{ language: 'mongo', scheme: 'untitled' },
|
||||
],
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
this.client = new LanguageClient('mongo', localize('mongo.server.name', 'Mongo Language Server'), serverOptions, clientOptions);
|
||||
this.client = new LanguageClient(
|
||||
'mongo',
|
||||
localize('mongo.server.name', 'Mongo Language Server'),
|
||||
serverOptions,
|
||||
clientOptions,
|
||||
);
|
||||
const disposable = this.client.start();
|
||||
|
||||
// Push the disposable to the context's subscriptions so that the
|
||||
|
@ -49,7 +53,11 @@ export class MongoDBLanguageClient {
|
|||
}
|
||||
|
||||
public async connect(connectionString: string, databaseName: string): Promise<void> {
|
||||
await this.client.sendRequest('connect', <IConnectionParams>{ connectionString: connectionString, databaseName: databaseName, extensionUserAgent: appendExtensionUserAgent() });
|
||||
await this.client.sendRequest('connect', <IConnectionParams>{
|
||||
connectionString: connectionString,
|
||||
databaseName: databaseName,
|
||||
extensionUserAgent: appendExtensionUserAgent(),
|
||||
});
|
||||
}
|
||||
|
||||
public async disconnect(): Promise<void> {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { createConnection, IConnection } from 'vscode-languageserver';
|
||||
import { createConnection, type IConnection } from 'vscode-languageserver';
|
||||
import { LanguageService } from './services/languageService';
|
||||
|
||||
//
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { appendExtensionUserAgent, IParsedError, parseError } from "@microsoft/vscode-azext-utils";
|
||||
import { MongoClient } from "mongodb";
|
||||
import { ParsedConnectionString } from "../ParsedConnectionString";
|
||||
import { nonNullValue } from "../utils/nonNull";
|
||||
import { connectToMongoClient } from "./connectToMongoClient";
|
||||
import { appendExtensionUserAgent, parseError, type IParsedError } from '@microsoft/vscode-azext-utils';
|
||||
import { type MongoClient } from 'mongodb';
|
||||
import { ParsedConnectionString } from '../ParsedConnectionString';
|
||||
import { nonNullValue } from '../utils/nonNull';
|
||||
import { connectToMongoClient } from './connectToMongoClient';
|
||||
|
||||
// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/):
|
||||
// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
|
||||
|
@ -20,15 +20,18 @@ import { connectToMongoClient } from "./connectToMongoClient";
|
|||
// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]]
|
||||
// [database]
|
||||
|
||||
const parsePrefix = '([a-zA-Z]+:\/\/[^\/]*)';
|
||||
const parseDatabaseName = '\/?([^/?]+)?';
|
||||
const parsePrefix = '([a-zA-Z]+://[^/]*)';
|
||||
const parseDatabaseName = '/?([^/?]+)?';
|
||||
const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName);
|
||||
|
||||
export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined {
|
||||
try {
|
||||
const [, , databaseName] = nonNullValue(connectionString.match(mongoConnectionStringRegExp), 'databaseNameMatch');
|
||||
const [, , databaseName] = nonNullValue(
|
||||
connectionString.match(mongoConnectionStringRegExp),
|
||||
'databaseNameMatch',
|
||||
);
|
||||
return databaseName;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Shouldn't happen, but ignore if does
|
||||
}
|
||||
|
||||
|
@ -37,15 +40,14 @@ export function getDatabaseNameFromConnectionString(connectionString: string): s
|
|||
|
||||
export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string {
|
||||
try {
|
||||
return connectionString.replace(mongoConnectionStringRegExp, `$1\/${encodeURIComponent(databaseName)}`);
|
||||
} catch (error) {
|
||||
return connectionString.replace(mongoConnectionStringRegExp, `$1/${encodeURIComponent(databaseName)}`);
|
||||
} catch {
|
||||
// Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it
|
||||
return connectionString;
|
||||
}
|
||||
}
|
||||
|
||||
export async function parseMongoConnectionString(connectionString: string): Promise<ParsedMongoConnectionString> {
|
||||
|
||||
let mongoClient: MongoClient;
|
||||
try {
|
||||
mongoClient = await connectToMongoClient(connectionString, appendExtensionUserAgent());
|
||||
|
@ -62,7 +64,12 @@ export async function parseMongoConnectionString(connectionString: string): Prom
|
|||
|
||||
const { host, port } = mongoClient.options.hosts[0];
|
||||
|
||||
return new ParsedMongoConnectionString(connectionString, host as string, (port as number).toString(), getDatabaseNameFromConnectionString(connectionString));
|
||||
return new ParsedMongoConnectionString(
|
||||
connectionString,
|
||||
host as string,
|
||||
(port as number).toString(),
|
||||
getDatabaseNameFromConnectionString(connectionString),
|
||||
);
|
||||
}
|
||||
|
||||
export class ParsedMongoConnectionString extends ParsedConnectionString {
|
||||
|
|
|
@ -3,25 +3,32 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { callWithTelemetryAndErrorHandling, IActionContext, IErrorHandlerContext, registerCommandWithTreeNodeUnwrapping, registerErrorHandler, registerEvent } from "@microsoft/vscode-azext-utils";
|
||||
import {
|
||||
callWithTelemetryAndErrorHandling,
|
||||
registerCommandWithTreeNodeUnwrapping,
|
||||
registerErrorHandler,
|
||||
registerEvent,
|
||||
type IActionContext,
|
||||
type IErrorHandlerContext,
|
||||
} from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ext } from "../extensionVariables";
|
||||
import { connectMongoDatabase, loadPersistedMongoDB } from "./commands/connectMongoDatabase";
|
||||
import { createMongoCollection } from "./commands/createMongoCollection";
|
||||
import { createMongoDatabase } from "./commands/createMongoDatabase";
|
||||
import { createMongoDocument } from "./commands/createMongoDocument";
|
||||
import { createMongoSrapbook } from "./commands/createMongoScrapbook";
|
||||
import { deleteMongoCollection } from "./commands/deleteMongoCollection";
|
||||
import { deleteMongoDB } from "./commands/deleteMongoDatabase";
|
||||
import { deleteMongoDocument } from "./commands/deleteMongoDocument";
|
||||
import { executeAllMongoCommand } from "./commands/executeAllMongoCommand";
|
||||
import { executeMongoCommand } from "./commands/executeMongoCommand";
|
||||
import { launchMongoShell } from "./commands/launchMongoShell";
|
||||
import { openMongoCollection } from "./commands/openMongoCollection";
|
||||
import { ext } from '../extensionVariables';
|
||||
import { connectMongoDatabase, loadPersistedMongoDB } from './commands/connectMongoDatabase';
|
||||
import { createMongoCollection } from './commands/createMongoCollection';
|
||||
import { createMongoDatabase } from './commands/createMongoDatabase';
|
||||
import { createMongoDocument } from './commands/createMongoDocument';
|
||||
import { createMongoSrapbook } from './commands/createMongoScrapbook';
|
||||
import { deleteMongoCollection } from './commands/deleteMongoCollection';
|
||||
import { deleteMongoDB } from './commands/deleteMongoDatabase';
|
||||
import { deleteMongoDocument } from './commands/deleteMongoDocument';
|
||||
import { executeAllMongoCommand } from './commands/executeAllMongoCommand';
|
||||
import { executeMongoCommand } from './commands/executeMongoCommand';
|
||||
import { launchMongoShell } from './commands/launchMongoShell';
|
||||
import { openMongoCollection } from './commands/openMongoCollection';
|
||||
import { MongoConnectError } from './connectToMongoClient';
|
||||
import { MongoDBLanguageClient } from "./languageClient";
|
||||
import { getAllErrorsFromTextDocument } from "./MongoScrapbook";
|
||||
import { MongoCodeLensProvider } from "./services/MongoCodeLensProvider";
|
||||
import { MongoDBLanguageClient } from './languageClient';
|
||||
import { getAllErrorsFromTextDocument } from './MongoScrapbook';
|
||||
import { MongoCodeLensProvider } from './services/MongoCodeLensProvider';
|
||||
|
||||
let diagnosticsCollection: vscode.DiagnosticCollection;
|
||||
const mongoLanguageId: string = 'mongo';
|
||||
|
@ -30,7 +37,9 @@ export function registerMongoCommands(): void {
|
|||
ext.mongoLanguageClient = new MongoDBLanguageClient();
|
||||
|
||||
ext.mongoCodeLensProvider = new MongoCodeLensProvider();
|
||||
ext.context.subscriptions.push(vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider));
|
||||
ext.context.subscriptions.push(
|
||||
vscode.languages.registerCodeLensProvider(mongoLanguageId, ext.mongoCodeLensProvider),
|
||||
);
|
||||
|
||||
diagnosticsCollection = vscode.languages.createDiagnosticCollection('cosmosDB.mongo');
|
||||
ext.context.subscriptions.push(diagnosticsCollection);
|
||||
|
@ -74,14 +83,16 @@ export function registerMongoCommands(): void {
|
|||
|
||||
function setUpErrorReporting(): void {
|
||||
// Update errors immediately in case a scrapbook is already open
|
||||
void callWithTelemetryAndErrorHandling(
|
||||
"initialUpdateErrorsInActiveDocument",
|
||||
async (context: IActionContext) => {
|
||||
updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document);
|
||||
});
|
||||
void callWithTelemetryAndErrorHandling('initialUpdateErrorsInActiveDocument', async (context: IActionContext) => {
|
||||
updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document);
|
||||
});
|
||||
|
||||
// Update errors when document opened/changed
|
||||
registerEvent('vscode.workspace.onDidOpenTextDocument', vscode.workspace.onDidOpenTextDocument, updateErrorsInScrapbook);
|
||||
registerEvent(
|
||||
'vscode.workspace.onDidOpenTextDocument',
|
||||
vscode.workspace.onDidOpenTextDocument,
|
||||
updateErrorsInScrapbook,
|
||||
);
|
||||
registerEvent(
|
||||
'vscode.workspace.onDidChangeTextDocument',
|
||||
vscode.workspace.onDidChangeTextDocument,
|
||||
|
@ -90,7 +101,8 @@ function setUpErrorReporting(): void {
|
|||
context.telemetry.suppressIfSuccessful = true;
|
||||
|
||||
updateErrorsInScrapbook(context, event.document);
|
||||
});
|
||||
},
|
||||
);
|
||||
registerEvent(
|
||||
'vscode.workspace.onDidCloseTextDocument',
|
||||
vscode.workspace.onDidCloseTextDocument,
|
||||
|
@ -101,7 +113,8 @@ function setUpErrorReporting(): void {
|
|||
} else {
|
||||
context.telemetry.suppressIfSuccessful = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
registerErrorHandler((context: IErrorHandlerContext) => {
|
||||
if (context.error instanceof MongoConnectError) {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils";
|
||||
import * as vscode from "vscode";
|
||||
import { getAllCommandsFromTextDocument } from "../MongoScrapbook";
|
||||
import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { getAllCommandsFromTextDocument } from '../MongoScrapbook';
|
||||
|
||||
export class MongoCodeLensProvider implements vscode.CodeLensProvider {
|
||||
private _onDidChangeEmitter: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
||||
|
@ -22,8 +22,11 @@ export class MongoCodeLensProvider implements vscode.CodeLensProvider {
|
|||
this._onDidChangeEmitter.fire();
|
||||
}
|
||||
|
||||
public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeLens[]> {
|
||||
return callWithTelemetryAndErrorHandling("mongo.provideCodeLenses", (context: IActionContext) => {
|
||||
public provideCodeLenses(
|
||||
document: vscode.TextDocument,
|
||||
_token: vscode.CancellationToken,
|
||||
): vscode.ProviderResult<vscode.CodeLens[]> {
|
||||
return callWithTelemetryAndErrorHandling('mongo.provideCodeLenses', (context: IActionContext) => {
|
||||
// Suppress except for errors - this can fire on every keystroke
|
||||
context.telemetry.suppressIfSuccessful = true;
|
||||
|
||||
|
@ -35,24 +38,24 @@ export class MongoCodeLensProvider implements vscode.CodeLensProvider {
|
|||
// Allow displaying and changing connected database
|
||||
lenses.push(<vscode.CodeLens>{
|
||||
command: {
|
||||
title: !isInitialized ?
|
||||
'Initializing...' :
|
||||
isConnected ?
|
||||
`Connected to ${database}` :
|
||||
`Connect to a database`,
|
||||
command: isInitialized && 'cosmosDB.connectMongoDB'
|
||||
title: !isInitialized
|
||||
? 'Initializing...'
|
||||
: isConnected
|
||||
? `Connected to ${database}`
|
||||
: `Connect to a database`,
|
||||
command: isInitialized && 'cosmosDB.connectMongoDB',
|
||||
},
|
||||
range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0))
|
||||
range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)),
|
||||
});
|
||||
|
||||
if (isConnected) {
|
||||
// Run all
|
||||
lenses.push(<vscode.CodeLens>{
|
||||
command: {
|
||||
title: "Execute All",
|
||||
command: 'cosmosDB.executeAllMongoCommands'
|
||||
title: 'Execute All',
|
||||
command: 'cosmosDB.executeAllMongoCommands',
|
||||
},
|
||||
range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0))
|
||||
range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)),
|
||||
});
|
||||
|
||||
const commands = getAllCommandsFromTextDocument(document);
|
||||
|
@ -60,11 +63,11 @@ export class MongoCodeLensProvider implements vscode.CodeLensProvider {
|
|||
// run individual
|
||||
lenses.push(<vscode.CodeLens>{
|
||||
command: {
|
||||
title: "Execute",
|
||||
title: 'Execute',
|
||||
command: 'cosmosDB.executeMongoCommand',
|
||||
arguments: [cmd.range.start]
|
||||
arguments: [cmd.range.start],
|
||||
},
|
||||
range: cmd.range
|
||||
range: cmd.range,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
|
||||
import { ParserRuleContext } from 'antlr4ts/ParserRuleContext';
|
||||
import { ErrorNode } from 'antlr4ts/tree/ErrorNode';
|
||||
import { ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { type ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
||||
import { Db } from 'mongodb';
|
||||
import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice';
|
||||
import { CompletionItem, CompletionItemKind, Position, Range } from 'vscode-languageserver';
|
||||
import { type Db } from 'mongodb';
|
||||
import { type LanguageService as JsonLanguageService } from 'vscode-json-languageservice';
|
||||
import { CompletionItemKind, Position, Range, type CompletionItem } from 'vscode-languageserver';
|
||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import { mongoLexer } from './../grammar/mongoLexer';
|
||||
import * as mongoParser from './../grammar/mongoParser';
|
||||
import { MongoVisitor } from './../grammar/visitors';
|
||||
import { SchemaService } from './schemaService';
|
||||
import { type SchemaService } from './schemaService';
|
||||
|
||||
export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[]>> {
|
||||
private at: Position;
|
||||
|
@ -26,7 +26,7 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
private db: Db,
|
||||
private offset: number,
|
||||
private schemaService: SchemaService,
|
||||
private jsonLanguageService: JsonLanguageService
|
||||
private jsonLanguageService: JsonLanguageService,
|
||||
) {
|
||||
super();
|
||||
this.at = this.textDocument.positionAt(this.offset);
|
||||
|
@ -53,8 +53,13 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
}
|
||||
|
||||
public visitCollection(ctx: mongoParser.CollectionContext): Promise<CompletionItem[]> {
|
||||
return Promise.all([this.createCollectionCompletions(this.createRange(ctx)), this.createDbFunctionCompletions(this.createRange(ctx))])
|
||||
.then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]);
|
||||
return Promise.all([
|
||||
this.createCollectionCompletions(this.createRange(ctx)),
|
||||
this.createDbFunctionCompletions(this.createRange(ctx)),
|
||||
]).then(([collectionCompletions, dbFunctionCompletions]) => [
|
||||
...collectionCompletions,
|
||||
...dbFunctionCompletions,
|
||||
]);
|
||||
}
|
||||
|
||||
public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise<CompletionItem[]> {
|
||||
|
@ -81,8 +86,23 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
const functionName = this.getFunctionName(ctx);
|
||||
const collectionName = this.getCollectionName(ctx);
|
||||
if (collectionName && functionName) {
|
||||
if (['find', 'findOne', 'findOneAndDelete', 'findOneAndUpdate', 'findOneAndReplace', 'deleteOne', 'deleteMany', 'remove'].indexOf(functionName) !== -1) {
|
||||
return this.getArgumentCompletionItems(this.schemaService.queryDocumentUri(collectionName), collectionName, ctx);
|
||||
if (
|
||||
[
|
||||
'find',
|
||||
'findOne',
|
||||
'findOneAndDelete',
|
||||
'findOneAndUpdate',
|
||||
'findOneAndReplace',
|
||||
'deleteOne',
|
||||
'deleteMany',
|
||||
'remove',
|
||||
].indexOf(functionName) !== -1
|
||||
) {
|
||||
return this.getArgumentCompletionItems(
|
||||
this.schemaService.queryDocumentUri(collectionName),
|
||||
collectionName,
|
||||
ctx,
|
||||
);
|
||||
}
|
||||
}
|
||||
return ctx.parent!.accept(this);
|
||||
|
@ -93,7 +113,11 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
const collectionName = this.getCollectionName(ctx);
|
||||
if (collectionName && functionName) {
|
||||
if (['aggregate'].indexOf(functionName) !== -1) {
|
||||
return this.getArgumentCompletionItems(this.schemaService.aggregateDocumentUri(collectionName), collectionName, ctx);
|
||||
return this.getArgumentCompletionItems(
|
||||
this.schemaService.aggregateDocumentUri(collectionName),
|
||||
collectionName,
|
||||
ctx,
|
||||
);
|
||||
}
|
||||
}
|
||||
return ctx.parent!.accept(this);
|
||||
|
@ -131,18 +155,31 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
return ctx.parent!.accept(this);
|
||||
}
|
||||
|
||||
private getArgumentCompletionItems(documentUri: string, _collectionName: string, ctx: ParserRuleContext): Thenable<CompletionItem[]> {
|
||||
private getArgumentCompletionItems(
|
||||
documentUri: string,
|
||||
_collectionName: string,
|
||||
ctx: ParserRuleContext,
|
||||
): Thenable<CompletionItem[]> {
|
||||
const text = this.textDocument.getText();
|
||||
const document = TextDocument.create(documentUri, 'json', 1, text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1));
|
||||
const document = TextDocument.create(
|
||||
documentUri,
|
||||
'json',
|
||||
1,
|
||||
text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1),
|
||||
);
|
||||
const positionOffset = this.textDocument.offsetAt(this.at);
|
||||
const contextOffset = ctx.start.startIndex;
|
||||
const position = document.positionAt(positionOffset - contextOffset);
|
||||
return this.jsonLanguageService.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document))
|
||||
.then(list => {
|
||||
return list!.items.map(item => {
|
||||
return this.jsonLanguageService
|
||||
.doComplete(document, position, this.jsonLanguageService.parseJSONDocument(document))
|
||||
.then((list) => {
|
||||
return list!.items.map((item) => {
|
||||
const startPositionOffset = document.offsetAt(item.textEdit!.range.start);
|
||||
const endPositionOffset = document.offsetAt(item.textEdit!.range.end);
|
||||
item.textEdit!.range = Range.create(this.textDocument.positionAt(startPositionOffset + contextOffset), this.textDocument.positionAt(contextOffset + endPositionOffset));
|
||||
item.textEdit!.range = Range.create(
|
||||
this.textDocument.positionAt(startPositionOffset + contextOffset),
|
||||
this.textDocument.positionAt(contextOffset + endPositionOffset),
|
||||
);
|
||||
return item;
|
||||
});
|
||||
});
|
||||
|
@ -198,8 +235,13 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
const previousNode = this.getPreviousNode(node);
|
||||
if (previousNode && previousNode instanceof TerminalNode) {
|
||||
if (previousNode._symbol.type === mongoParser.mongoParser.DB) {
|
||||
return Promise.all([this.createCollectionCompletions(this.createRangeAfter(node)), this.createDbFunctionCompletions(this.createRangeAfter(node))])
|
||||
.then(([collectionCompletions, dbFunctionCompletions]) => [...collectionCompletions, ...dbFunctionCompletions]);
|
||||
return Promise.all([
|
||||
this.createCollectionCompletions(this.createRangeAfter(node)),
|
||||
this.createDbFunctionCompletions(this.createRangeAfter(node)),
|
||||
]).then(([collectionCompletions, dbFunctionCompletions]) => [
|
||||
...collectionCompletions,
|
||||
...dbFunctionCompletions,
|
||||
]);
|
||||
}
|
||||
}
|
||||
if (previousNode instanceof mongoParser.CollectionContext) {
|
||||
|
@ -219,7 +261,15 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
}
|
||||
|
||||
private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode {
|
||||
return ctx.children ? <TerminalNode>ctx.children.slice().reverse().filter(node => node instanceof TerminalNode && node.symbol.stopIndex > -1 && node.symbol.stopIndex < this.offset)[0] : null!;
|
||||
return ctx.children ? <TerminalNode>ctx.children
|
||||
.slice()
|
||||
.reverse()
|
||||
.filter(
|
||||
(node) =>
|
||||
node instanceof TerminalNode &&
|
||||
node.symbol.stopIndex > -1 &&
|
||||
node.symbol.stopIndex < this.offset,
|
||||
)[0] : null!;
|
||||
}
|
||||
|
||||
private getPreviousNode(node: ParseTree): ParseTree {
|
||||
|
@ -239,10 +289,10 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
return {
|
||||
textEdit: {
|
||||
newText: 'db',
|
||||
range
|
||||
range,
|
||||
},
|
||||
kind: CompletionItemKind.Keyword,
|
||||
label: 'db'
|
||||
label: 'db',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -296,23 +346,26 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
this.createFunctionCompletion('setVerboseShell', range),
|
||||
this.createFunctionCompletion('shotdownServer', range),
|
||||
this.createFunctionCompletion('stats', range),
|
||||
this.createFunctionCompletion('version', range)
|
||||
this.createFunctionCompletion('version', range),
|
||||
);
|
||||
}
|
||||
|
||||
private createCollectionCompletions(range: Range): Promise<CompletionItem[]> {
|
||||
if (this.db) {
|
||||
return <Promise<CompletionItem[]>>this.db.collections().then(collections => {
|
||||
return collections.map(collection => (<CompletionItem>{
|
||||
textEdit: {
|
||||
newText: collection.collectionName,
|
||||
range
|
||||
},
|
||||
label: collection.collectionName,
|
||||
kind: CompletionItemKind.Property,
|
||||
filterText: collection.collectionName,
|
||||
sortText: `1:${collection.collectionName}`
|
||||
}));
|
||||
return <Promise<CompletionItem[]>>this.db.collections().then((collections) => {
|
||||
return collections.map(
|
||||
(collection) =>
|
||||
<CompletionItem>{
|
||||
textEdit: {
|
||||
newText: collection.collectionName,
|
||||
range,
|
||||
},
|
||||
label: collection.collectionName,
|
||||
kind: CompletionItemKind.Property,
|
||||
filterText: collection.collectionName,
|
||||
sortText: `1:${collection.collectionName}`,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
|
@ -368,7 +421,7 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
this.createFunctionCompletion('getWriteConcern', range),
|
||||
this.createFunctionCompletion('setWriteConcern', range),
|
||||
this.createFunctionCompletion('unsetWriteConcern', range),
|
||||
this.createFunctionCompletion('latencyStats', range)
|
||||
this.createFunctionCompletion('latencyStats', range),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -376,11 +429,11 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
return {
|
||||
textEdit: {
|
||||
newText: label,
|
||||
range
|
||||
range,
|
||||
},
|
||||
kind: CompletionItemKind.Function,
|
||||
label,
|
||||
sortText: `2:${label}`
|
||||
sortText: `2:${label}`,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -435,5 +488,4 @@ export class CompletionItemsVisitor extends MongoVisitor<Promise<CompletionItem[
|
|||
private thenable(...completionItems: CompletionItem[]): Promise<CompletionItem[]> {
|
||||
return Promise.resolve(completionItems || []);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,17 +5,28 @@
|
|||
|
||||
// NOTE: This file may not take a dependencey on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils)
|
||||
|
||||
import { Db } from 'mongodb';
|
||||
import { getLanguageService, LanguageService as JsonLanguageService, SchemaConfiguration } from 'vscode-json-languageservice';
|
||||
import { CompletionItem, IConnection, InitializeParams, InitializeResult, TextDocumentPositionParams, TextDocuments, TextDocumentSyncKind } from 'vscode-languageserver';
|
||||
import { type Db } from 'mongodb';
|
||||
import {
|
||||
getLanguageService,
|
||||
type LanguageService as JsonLanguageService,
|
||||
type SchemaConfiguration,
|
||||
} from 'vscode-json-languageservice';
|
||||
import {
|
||||
TextDocuments,
|
||||
TextDocumentSyncKind,
|
||||
type CompletionItem,
|
||||
type IConnection,
|
||||
type InitializeParams,
|
||||
type InitializeResult,
|
||||
type TextDocumentPositionParams,
|
||||
} from 'vscode-languageserver';
|
||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import { connectToMongoClient } from '../connectToMongoClient';
|
||||
import { IConnectionParams } from './IConnectionParams';
|
||||
import { type IConnectionParams } from './IConnectionParams';
|
||||
import { MongoScriptDocumentManager } from './mongoScript';
|
||||
import { SchemaService } from './schemaService';
|
||||
|
||||
export class LanguageService {
|
||||
|
||||
private textDocuments: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
|
||||
private readonly mongoDocumentsManager: MongoScriptDocumentManager;
|
||||
private db: Db;
|
||||
|
@ -25,7 +36,6 @@ export class LanguageService {
|
|||
private schemas: SchemaConfiguration[];
|
||||
|
||||
constructor(connection: IConnection) {
|
||||
|
||||
this.schemaService = new SchemaService();
|
||||
|
||||
this.textDocuments.listen(connection);
|
||||
|
@ -35,24 +45,24 @@ export class LanguageService {
|
|||
return {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode
|
||||
completionProvider: { triggerCharacters: ['.'] }
|
||||
}
|
||||
completionProvider: { triggerCharacters: ['.'] },
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
connection.onCompletion(textDocumentPosition => {
|
||||
connection.onCompletion((textDocumentPosition) => {
|
||||
return this.provideCompletionItems(textDocumentPosition);
|
||||
});
|
||||
|
||||
connection.onRequest('connect', (connectionParams: IConnectionParams) => {
|
||||
void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent)
|
||||
.then(account => {
|
||||
void connectToMongoClient(connectionParams.connectionString, connectionParams.extensionUserAgent).then(
|
||||
(account) => {
|
||||
this.db = account.db(connectionParams.databaseName);
|
||||
void this.schemaService.registerSchemas(this.db)
|
||||
.then(schemas => {
|
||||
this.configureSchemas(schemas);
|
||||
});
|
||||
});
|
||||
void this.schemaService.registerSchemas(this.db).then((schemas) => {
|
||||
this.configureSchemas(schemas);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
connection.onRequest('disconnect', () => {
|
||||
|
@ -64,8 +74,8 @@ export class LanguageService {
|
|||
});
|
||||
|
||||
this.jsonLanguageService = getLanguageService({
|
||||
schemaRequestService: uri => this.schemaService.resolveSchema(uri),
|
||||
contributions: []
|
||||
schemaRequestService: (uri) => this.schemaService.resolveSchema(uri),
|
||||
contributions: [],
|
||||
});
|
||||
|
||||
this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService);
|
||||
|
@ -84,7 +94,7 @@ export class LanguageService {
|
|||
|
||||
public configureSchemas(schemas: SchemaConfiguration[]): void {
|
||||
this.jsonLanguageService.configure({
|
||||
schemas
|
||||
schemas,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,25 +6,23 @@ import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream';
|
|||
import { CommonTokenStream } from 'antlr4ts/CommonTokenStream';
|
||||
import { Interval } from 'antlr4ts/misc/Interval';
|
||||
import { ParserRuleContext } from 'antlr4ts/ParserRuleContext';
|
||||
import { ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { type ParseTree } from 'antlr4ts/tree/ParseTree';
|
||||
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
||||
import { Db } from 'mongodb';
|
||||
import { LanguageService as JsonLanguageService } from 'vscode-json-languageservice';
|
||||
import { CompletionItem, Position } from 'vscode-languageserver';
|
||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import { type Db } from 'mongodb';
|
||||
import { type LanguageService as JsonLanguageService } from 'vscode-json-languageservice';
|
||||
import { type CompletionItem, type Position } from 'vscode-languageserver';
|
||||
import { type TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import { mongoLexer } from './../grammar/mongoLexer';
|
||||
import * as mongoParser from './../grammar/mongoParser';
|
||||
import { MongoVisitor } from './../grammar/visitors';
|
||||
import { CompletionItemsVisitor } from './completionItemProvider';
|
||||
import { SchemaService } from './schemaService';
|
||||
import { type SchemaService } from './schemaService';
|
||||
|
||||
export class MongoScriptDocumentManager {
|
||||
|
||||
constructor(
|
||||
private schemaService: SchemaService,
|
||||
private jsonLanguageService: JsonLanguageService
|
||||
) {
|
||||
}
|
||||
private jsonLanguageService: JsonLanguageService,
|
||||
) {}
|
||||
|
||||
public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument {
|
||||
return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService);
|
||||
|
@ -32,14 +30,13 @@ export class MongoScriptDocumentManager {
|
|||
}
|
||||
|
||||
export class MongoScriptDocument {
|
||||
|
||||
private readonly _lexer: mongoLexer;
|
||||
|
||||
constructor(
|
||||
private textDocument: TextDocument,
|
||||
private db: Db,
|
||||
private schemaService: SchemaService,
|
||||
private jsonLanguageService: JsonLanguageService
|
||||
private jsonLanguageService: JsonLanguageService,
|
||||
) {
|
||||
this._lexer = new mongoLexer(new InputStream(textDocument.getText()));
|
||||
this._lexer.removeErrorListeners();
|
||||
|
@ -52,14 +49,19 @@ export class MongoScriptDocument {
|
|||
const offset = this.textDocument.offsetAt(position);
|
||||
const lastNode = new NodeFinder(offset).visit(parser.commands());
|
||||
if (lastNode) {
|
||||
return new CompletionItemsVisitor(this.textDocument, this.db, offset, this.schemaService, this.jsonLanguageService).visit(lastNode);
|
||||
return new CompletionItemsVisitor(
|
||||
this.textDocument,
|
||||
this.db,
|
||||
offset,
|
||||
this.schemaService,
|
||||
this.jsonLanguageService,
|
||||
).visit(lastNode);
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
class NodeFinder extends MongoVisitor<ParseTree> {
|
||||
|
||||
constructor(private offset: number) {
|
||||
super();
|
||||
}
|
||||
|
@ -86,12 +88,28 @@ class NodeFinder extends MongoVisitor<ParseTree> {
|
|||
|
||||
protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree {
|
||||
if (aggregate && nextResult) {
|
||||
const aggregateStart = aggregate instanceof ParserRuleContext ? aggregate.start.startIndex : (<TerminalNode>aggregate).symbol.startIndex;
|
||||
const aggregateStop = aggregate instanceof ParserRuleContext ? aggregate.start.stopIndex : (<TerminalNode>aggregate).symbol.stopIndex;
|
||||
const nextResultStart = nextResult instanceof ParserRuleContext ? nextResult.start.startIndex : (<TerminalNode>nextResult).symbol.startIndex;
|
||||
const nextResultStop = nextResult instanceof ParserRuleContext ? nextResult.start.stopIndex : (<TerminalNode>nextResult).symbol.stopIndex;
|
||||
const aggregateStart =
|
||||
aggregate instanceof ParserRuleContext
|
||||
? aggregate.start.startIndex
|
||||
: (<TerminalNode>aggregate).symbol.startIndex;
|
||||
const aggregateStop =
|
||||
aggregate instanceof ParserRuleContext
|
||||
? aggregate.start.stopIndex
|
||||
: (<TerminalNode>aggregate).symbol.stopIndex;
|
||||
const nextResultStart =
|
||||
nextResult instanceof ParserRuleContext
|
||||
? nextResult.start.startIndex
|
||||
: (<TerminalNode>nextResult).symbol.startIndex;
|
||||
const nextResultStop =
|
||||
nextResult instanceof ParserRuleContext
|
||||
? nextResult.start.stopIndex
|
||||
: (<TerminalNode>nextResult).symbol.stopIndex;
|
||||
|
||||
if (Interval.of(aggregateStart, aggregateStop).properlyContains(Interval.of(nextResultStart, nextResultStop))) {
|
||||
if (
|
||||
Interval.of(aggregateStart, aggregateStop).properlyContains(
|
||||
Interval.of(nextResultStart, nextResultStop),
|
||||
)
|
||||
) {
|
||||
return aggregate;
|
||||
}
|
||||
return nextResult;
|
||||
|
|
|
@ -5,33 +5,36 @@
|
|||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-member-access */
|
||||
|
||||
import { Db, FindCursor } from 'mongodb';
|
||||
import { SchemaConfiguration } from 'vscode-json-languageservice';
|
||||
import { type Db, type FindCursor } from 'mongodb';
|
||||
import { type SchemaConfiguration } from 'vscode-json-languageservice';
|
||||
// eslint-disable-next-line import/no-internal-modules
|
||||
import { JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema';
|
||||
import { type JSONSchema } from 'vscode-json-languageservice/lib/umd/jsonSchema';
|
||||
|
||||
export class SchemaService {
|
||||
|
||||
private _db: Db;
|
||||
private _schemasCache: Map<string, string> = new Map<string, string>();
|
||||
|
||||
public registerSchemas(db: Db): Thenable<SchemaConfiguration[]> {
|
||||
this._db = db;
|
||||
this._schemasCache.clear();
|
||||
return this._db.collections()
|
||||
.then(collections => {
|
||||
const schemas: SchemaConfiguration[] = [];
|
||||
for (const collection of collections) {
|
||||
schemas.push(...[{
|
||||
uri: this.queryCollectionSchema(collection.collectionName),
|
||||
fileMatch: [this.queryDocumentUri(collection.collectionName)]
|
||||
}, {
|
||||
uri: this.aggregateCollectionSchema(collection.collectionName),
|
||||
fileMatch: [this.aggregateDocumentUri(collection.collectionName)]
|
||||
}]);
|
||||
}
|
||||
return schemas;
|
||||
});
|
||||
return this._db.collections().then((collections) => {
|
||||
const schemas: SchemaConfiguration[] = [];
|
||||
for (const collection of collections) {
|
||||
schemas.push(
|
||||
...[
|
||||
{
|
||||
uri: this.queryCollectionSchema(collection.collectionName),
|
||||
fileMatch: [this.queryDocumentUri(collection.collectionName)],
|
||||
},
|
||||
{
|
||||
uri: this.aggregateCollectionSchema(collection.collectionName),
|
||||
fileMatch: [this.aggregateDocumentUri(collection.collectionName)],
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
return schemas;
|
||||
});
|
||||
}
|
||||
|
||||
public queryCollectionSchema(collectionName: string): string {
|
||||
|
@ -56,18 +59,21 @@ export class SchemaService {
|
|||
return Promise.resolve(schema);
|
||||
}
|
||||
if (uri.startsWith('mongo://query/')) {
|
||||
return this._resolveQueryCollectionSchema(uri.substring('mongo://query/'.length, uri.length - '.schema'.length), uri)
|
||||
.then(sch => {
|
||||
this._schemasCache.set(uri, sch);
|
||||
return sch;
|
||||
});
|
||||
return this._resolveQueryCollectionSchema(
|
||||
uri.substring('mongo://query/'.length, uri.length - '.schema'.length),
|
||||
uri,
|
||||
).then((sch) => {
|
||||
this._schemasCache.set(uri, sch);
|
||||
return sch;
|
||||
});
|
||||
}
|
||||
if (uri.startsWith('mongo://aggregate/')) {
|
||||
return this._resolveAggregateCollectionSchema(uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length))
|
||||
.then(sch => {
|
||||
this._schemasCache.set(uri, sch);
|
||||
return sch;
|
||||
});
|
||||
return this._resolveAggregateCollectionSchema(
|
||||
uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length),
|
||||
).then((sch) => {
|
||||
this._schemasCache.set(uri, sch);
|
||||
return sch;
|
||||
});
|
||||
}
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
@ -79,7 +85,7 @@ export class SchemaService {
|
|||
this.readNext([], cursor, 10, (result) => {
|
||||
const schema: JSONSchema = {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
properties: {},
|
||||
};
|
||||
for (const document of result) {
|
||||
this.setSchemaForDocument(null!, document, schema);
|
||||
|
@ -98,7 +104,7 @@ export class SchemaService {
|
|||
this.readNext([], cursor, 10, (_result) => {
|
||||
const schema: JSONSchema = {
|
||||
type: 'array',
|
||||
items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName))
|
||||
items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)),
|
||||
};
|
||||
resolve(JSON.stringify(schema));
|
||||
});
|
||||
|
@ -106,14 +112,14 @@ export class SchemaService {
|
|||
}
|
||||
|
||||
private getMongoDocumentType(document: any): string {
|
||||
return Array.isArray(document) ? 'array' : (document === null ? 'null' : typeof document);
|
||||
return Array.isArray(document) ? 'array' : document === null ? 'null' : typeof document;
|
||||
}
|
||||
|
||||
private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void {
|
||||
if (this.getMongoDocumentType(document) === 'object') {
|
||||
//eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
for (const property of Object.keys(document)) {
|
||||
if (!parent &&
|
||||
['_id'].indexOf(property) !== -1) {
|
||||
if (!parent && ['_id'].indexOf(property) !== -1) {
|
||||
continue;
|
||||
}
|
||||
this.setSchemaForDocumentProperty(parent, property, document, schema);
|
||||
|
@ -128,7 +134,7 @@ export class SchemaService {
|
|||
const type = this.getMongoDocumentType(value);
|
||||
|
||||
const propertySchema: JSONSchema = {
|
||||
type: [type, 'object']
|
||||
type: [type, 'object'],
|
||||
};
|
||||
this.setOperatorProperties(type, propertySchema);
|
||||
schema.properties![scopedProperty] = propertySchema;
|
||||
|
@ -151,57 +157,62 @@ export class SchemaService {
|
|||
properties: {
|
||||
$search: <JSONSchema>{
|
||||
type: 'string',
|
||||
description: 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase'
|
||||
description:
|
||||
'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase',
|
||||
},
|
||||
$language: {
|
||||
type: 'string',
|
||||
description: 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming'
|
||||
description:
|
||||
'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming',
|
||||
},
|
||||
$caseSensitive: {
|
||||
type: 'boolean',
|
||||
description: 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index'
|
||||
description:
|
||||
'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index',
|
||||
},
|
||||
$diacriticSensitive: {
|
||||
type: 'boolean',
|
||||
description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index
|
||||
Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`
|
||||
}
|
||||
Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`,
|
||||
},
|
||||
},
|
||||
required: ['$search']
|
||||
required: ['$search'],
|
||||
};
|
||||
|
||||
schema.properties!.$where = {
|
||||
type: 'string',
|
||||
description: `Matches documents that satisfy a JavaScript expression.
|
||||
Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`
|
||||
Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`,
|
||||
};
|
||||
schema.properties!.$comment = {
|
||||
type: 'string',
|
||||
description: 'Adds a comment to a query predicate'
|
||||
description: 'Adds a comment to a query predicate',
|
||||
};
|
||||
}
|
||||
|
||||
private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void {
|
||||
schema.properties!.$or = {
|
||||
type: 'array',
|
||||
description: 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause',
|
||||
description:
|
||||
'Joins query clauses with a logical OR returns all documents that match the conditions of either clause',
|
||||
items: <JSONSchema>{
|
||||
$ref: schemaUri
|
||||
}
|
||||
$ref: schemaUri,
|
||||
},
|
||||
};
|
||||
schema.properties!.$and = {
|
||||
type: 'array',
|
||||
description: 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses',
|
||||
description:
|
||||
'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses',
|
||||
items: <JSONSchema>{
|
||||
$ref: schemaUri
|
||||
}
|
||||
$ref: schemaUri,
|
||||
},
|
||||
};
|
||||
schema.properties!.$nor = {
|
||||
type: 'array',
|
||||
description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses',
|
||||
items: <JSONSchema>{
|
||||
$ref: schemaUri
|
||||
}
|
||||
$ref: schemaUri,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -212,62 +223,63 @@ Use the $where operator to pass either a string containing a JavaScript expressi
|
|||
|
||||
const expressionSchema = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
properties: <any>{}
|
||||
properties: <any>{},
|
||||
};
|
||||
// Comparison operators
|
||||
expressionSchema.properties.$eq = {
|
||||
type: type,
|
||||
description: 'Matches values that are equal to a specified value'
|
||||
description: 'Matches values that are equal to a specified value',
|
||||
};
|
||||
expressionSchema.properties.$gt = {
|
||||
type: type,
|
||||
description: 'Matches values that are greater than a specified value'
|
||||
description: 'Matches values that are greater than a specified value',
|
||||
};
|
||||
expressionSchema.properties.$gte = {
|
||||
type: type,
|
||||
description: 'Matches values that are greater than or equal to a specified value'
|
||||
description: 'Matches values that are greater than or equal to a specified value',
|
||||
};
|
||||
expressionSchema.properties.$lt = {
|
||||
type: type,
|
||||
description: 'Matches values that are less than a specified value'
|
||||
description: 'Matches values that are less than a specified value',
|
||||
};
|
||||
expressionSchema.properties.$lte = {
|
||||
type: type,
|
||||
description: 'Matches values that are less than or equal to a specified value'
|
||||
description: 'Matches values that are less than or equal to a specified value',
|
||||
};
|
||||
expressionSchema.properties.$ne = {
|
||||
type: type,
|
||||
description: 'Matches all values that are not equal to a specified value'
|
||||
description: 'Matches all values that are not equal to a specified value',
|
||||
};
|
||||
expressionSchema.properties.$in = {
|
||||
type: 'array',
|
||||
description: 'Matches any of the values specified in an array'
|
||||
description: 'Matches any of the values specified in an array',
|
||||
};
|
||||
expressionSchema.properties.$nin = {
|
||||
type: 'array',
|
||||
description: 'Matches none of the values specified in an array'
|
||||
description: 'Matches none of the values specified in an array',
|
||||
};
|
||||
|
||||
// Element operators
|
||||
expressionSchema.properties.$exists = {
|
||||
type: 'boolean',
|
||||
description: 'Matches documents that have the specified field'
|
||||
description: 'Matches documents that have the specified field',
|
||||
};
|
||||
expressionSchema.properties.$type = {
|
||||
type: 'string',
|
||||
description: 'Selects documents if a field is of the specified type'
|
||||
description: 'Selects documents if a field is of the specified type',
|
||||
};
|
||||
|
||||
// Evaluation operators
|
||||
expressionSchema.properties.$mod = {
|
||||
type: 'array',
|
||||
description: 'Performs a modulo operation on the value of a field and selects documents with a specified result',
|
||||
description:
|
||||
'Performs a modulo operation on the value of a field and selects documents with a specified result',
|
||||
maxItems: 2,
|
||||
default: [2, 0]
|
||||
default: [2, 0],
|
||||
};
|
||||
expressionSchema.properties.$regex = {
|
||||
type: 'string',
|
||||
description: 'Selects documents where values match a specified regular expression'
|
||||
description: 'Selects documents where values match a specified regular expression',
|
||||
};
|
||||
|
||||
// Geospatial
|
||||
|
@ -276,117 +288,124 @@ Use the $where operator to pass either a string containing a JavaScript expressi
|
|||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
default: 'GeoJSON object type'
|
||||
default: 'GeoJSON object type',
|
||||
},
|
||||
coordinates: {
|
||||
type: 'array'
|
||||
type: 'array',
|
||||
},
|
||||
crs: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string'
|
||||
type: 'string',
|
||||
},
|
||||
properties: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
expressionSchema.properties.$geoWithin = {
|
||||
type: 'object',
|
||||
description: 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin',
|
||||
description:
|
||||
'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin',
|
||||
properties: {
|
||||
$geometry: geometryPropertySchema,
|
||||
$box: {
|
||||
type: 'array'
|
||||
type: 'array',
|
||||
},
|
||||
$polygon: {
|
||||
type: 'array'
|
||||
type: 'array',
|
||||
},
|
||||
$center: {
|
||||
type: 'array'
|
||||
type: 'array',
|
||||
},
|
||||
$centerSphere: {
|
||||
type: 'array'
|
||||
}
|
||||
}
|
||||
type: 'array',
|
||||
},
|
||||
},
|
||||
};
|
||||
expressionSchema.properties.$geoIntersects = {
|
||||
type: 'object',
|
||||
description: 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects',
|
||||
description:
|
||||
'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects',
|
||||
properties: {
|
||||
$geometry: geometryPropertySchema
|
||||
}
|
||||
$geometry: geometryPropertySchema,
|
||||
},
|
||||
};
|
||||
expressionSchema.properties.$near = {
|
||||
type: 'object',
|
||||
description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near',
|
||||
description:
|
||||
'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near',
|
||||
properties: {
|
||||
$geometry: geometryPropertySchema,
|
||||
$maxDistance: {
|
||||
type: 'number'
|
||||
type: 'number',
|
||||
},
|
||||
$minDistance: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
};
|
||||
expressionSchema.properties.$nearSphere = {
|
||||
type: 'object',
|
||||
description: 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near',
|
||||
description:
|
||||
'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near',
|
||||
properties: {
|
||||
$geometry: geometryPropertySchema,
|
||||
$maxDistance: {
|
||||
type: 'number'
|
||||
type: 'number',
|
||||
},
|
||||
$minDistance: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Array operatos
|
||||
if (type === 'array') {
|
||||
expressionSchema.properties.$all = {
|
||||
type: 'array',
|
||||
description: 'Matches arrays that contain all elements specified in the query'
|
||||
description: 'Matches arrays that contain all elements specified in the query',
|
||||
};
|
||||
expressionSchema.properties.$size = {
|
||||
type: 'number',
|
||||
description: 'Selects documents if the array field is a specified size'
|
||||
description: 'Selects documents if the array field is a specified size',
|
||||
};
|
||||
}
|
||||
|
||||
// Bit operators
|
||||
expressionSchema.properties.$bitsAllSet = {
|
||||
type: 'array',
|
||||
description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1'
|
||||
description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1',
|
||||
};
|
||||
expressionSchema.properties.$bitsAnySet = {
|
||||
type: 'array',
|
||||
description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1'
|
||||
description:
|
||||
'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1',
|
||||
};
|
||||
expressionSchema.properties.$bitsAllClear = {
|
||||
type: 'array',
|
||||
description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0'
|
||||
description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0',
|
||||
};
|
||||
expressionSchema.properties.$bitsAnyClear = {
|
||||
type: 'array',
|
||||
description: 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0'
|
||||
description:
|
||||
'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0',
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
schema.properties = { ...expressionSchema.properties };
|
||||
schema.properties!.$not = {
|
||||
type: 'object',
|
||||
description: 'Inverts the effect of a query expression and returns documents that do not match the query expression',
|
||||
description:
|
||||
'Inverts the effect of a query expression and returns documents that do not match the query expression',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
properties: { ...expressionSchema.properties }
|
||||
properties: { ...expressionSchema.properties },
|
||||
};
|
||||
schema.properties!.$elemMatch = {
|
||||
type: 'object'
|
||||
type: 'object',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -397,232 +416,253 @@ Use the $where operator to pass either a string containing a JavaScript expressi
|
|||
properties: {
|
||||
$collStats: {
|
||||
type: 'object',
|
||||
description: 'Returns statistics regarding a collection or view'
|
||||
}
|
||||
}
|
||||
|
||||
description: 'Returns statistics regarding a collection or view',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$project: {
|
||||
type: 'object',
|
||||
description: 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$match: {
|
||||
type: 'object',
|
||||
description: 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)',
|
||||
$ref: querySchemaUri
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)',
|
||||
$ref: querySchemaUri,
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$redact: {
|
||||
type: 'object',
|
||||
description: 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$limit: {
|
||||
type: 'object',
|
||||
description: 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$skip: {
|
||||
type: 'object',
|
||||
description: 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$unwind: {
|
||||
type: 'object',
|
||||
description: 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$group: {
|
||||
type: 'object',
|
||||
description: 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.',
|
||||
description:
|
||||
'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.',
|
||||
properties: {
|
||||
_id: {
|
||||
type: ['string', 'object']
|
||||
}
|
||||
type: ['string', 'object'],
|
||||
},
|
||||
},
|
||||
additionalProperties: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$sample: {
|
||||
type: 'object',
|
||||
description: 'Randomly selects the specified number of documents from its input'
|
||||
}
|
||||
}
|
||||
description: 'Randomly selects the specified number of documents from its input',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$sort: {
|
||||
type: 'object',
|
||||
description: 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$geoNear: {
|
||||
type: 'object',
|
||||
description: 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$lookup: {
|
||||
type: 'object',
|
||||
description: 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$out: {
|
||||
type: 'object',
|
||||
description: 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$indexStats: {
|
||||
type: 'object',
|
||||
description: 'Returns statistics regarding the use of each index for the collection'
|
||||
}
|
||||
}
|
||||
description: 'Returns statistics regarding the use of each index for the collection',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$facet: {
|
||||
type: 'object',
|
||||
description: 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$bucket: {
|
||||
type: 'object',
|
||||
description: 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$bucketAuto: {
|
||||
type: 'object',
|
||||
description: 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$sortByCount: {
|
||||
type: 'object',
|
||||
description: 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$addFields: {
|
||||
type: 'object',
|
||||
description: 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$replaceRoot: {
|
||||
type: 'object',
|
||||
description: 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$count: {
|
||||
type: 'object',
|
||||
description: 'Returns a count of the number of documents at this stage of the aggregation pipeline'
|
||||
}
|
||||
}
|
||||
description: 'Returns a count of the number of documents at this stage of the aggregation pipeline',
|
||||
},
|
||||
},
|
||||
});
|
||||
schemas.push({
|
||||
type: 'object',
|
||||
properties: {
|
||||
$graphLookup: {
|
||||
type: 'object',
|
||||
description: 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document'
|
||||
}
|
||||
}
|
||||
description:
|
||||
'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document',
|
||||
},
|
||||
},
|
||||
});
|
||||
return {
|
||||
type: 'object',
|
||||
oneOf: schemas
|
||||
oneOf: schemas,
|
||||
};
|
||||
}
|
||||
|
||||
private readNext(result: any[], cursor: FindCursor<any>, batchSize: number, callback: (result: any[]) => void): void {
|
||||
private readNext(
|
||||
result: any[],
|
||||
cursor: FindCursor<any>,
|
||||
batchSize: number,
|
||||
callback: (result: any[]) => void,
|
||||
): void {
|
||||
if (result.length === batchSize) {
|
||||
callback(result);
|
||||
return;
|
||||
}
|
||||
|
||||
void cursor.hasNext().then(hasNext => {
|
||||
void cursor.hasNext().then((hasNext) => {
|
||||
if (!hasNext) {
|
||||
callback(result);
|
||||
return;
|
||||
}
|
||||
|
||||
void cursor.next().then(doc => {
|
||||
void cursor.next().then((doc) => {
|
||||
result.push(doc);
|
||||
this.readNext(result, cursor, batchSize, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ext } from "../extensionVariables";
|
||||
import { MongoDatabaseTreeItem } from "./tree/MongoDatabaseTreeItem";
|
||||
import { ext } from '../extensionVariables';
|
||||
import { type MongoDatabaseTreeItem } from './tree/MongoDatabaseTreeItem';
|
||||
|
||||
export function setConnectedNode(node: MongoDatabaseTreeItem | undefined): void {
|
||||
ext.connectedMongoDB = node;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче