From d45e10f5ac897b6bd628337665b94960ff2a93f7 Mon Sep 17 00:00:00 2001 From: Sung-Hyun Kang Date: Thu, 18 Sep 2025 08:01:01 -0500 Subject: [PATCH] Added VS Code Exnteion for DE --- src/Contracts/DataModels.ts | 6 ++++ src/Explorer/Explorer.tsx | 35 ++------------------ src/Utils/VSCodeExtensionUtils.ts | 54 +++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 33 deletions(-) create mode 100644 src/Utils/VSCodeExtensionUtils.ts diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index 7dfe33bbb..258fe20fe 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -44,6 +44,12 @@ export interface DatabaseAccountExtendedProperties { publicNetworkAccess?: string; enablePriorityBasedExecution?: boolean; vcoreMongoEndpoint?: string; + apiProperties?: ApiProperties; +} + +export interface ApiProperties { + /* Describes the version of the MongoDB account. */ + serverVersion?: "3.2" | "3.6" | "4.0" | "4.2" | "5.0" | "6.0" | "7.0"; } export interface DatabaseAccountResponseLocation { diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 91ad1b20b..28e5c2948 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -18,6 +18,7 @@ import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility"; import { acquireMsalTokenForAccount } from "Utils/AuthorizationUtils"; import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointUtils"; import { featureRegistered } from "Utils/FeatureRegistrationUtils"; +import { getVSCodeUrl } from "Utils/VSCodeExtensionUtils"; import { update } from "Utils/arm/generatedClients/cosmos/databaseAccounts"; import { useQueryCopilot } from "hooks/useQueryCopilot"; import * as ko from "knockout"; @@ -289,40 +290,8 @@ export default class Explorer { } } - /** - * Generates a VS Code DocumentDB connection URL using the current user's MongoDB connection parameters. - * Double-encodes the updated connection string for safe usage in VS Code URLs. - * - * The DocumentDB VS Code extension requires double encoding for connection strings. - * See: https://microsoft.github.io/vscode-documentdb/manual/how-to-construct-url.html#double-encoding - * - * @returns {string} The encoded VS Code DocumentDB connection URL. - */ - private getDocumentDbUrl() { - const { adminLogin: adminLoginuserName = "", connectionString = "" } = userContext.vcoreMongoConnectionParams; - const updatedConnectionString = connectionString.replace(/<(user|username)>:/i, adminLoginuserName); - const encodedUpdatedConnectionString = encodeURIComponent(encodeURIComponent(updatedConnectionString)); - const documentDbUrl = `vscode://ms-azuretools.vscode-documentdb?connectionString=${encodedUpdatedConnectionString}`; - return documentDbUrl; - } - - private getCosmosDbUrl() { - const activeTab = useTabs.getState().activeTab; - const resourceId = encodeURIComponent(userContext.databaseAccount.id); - const database = encodeURIComponent(activeTab?.collection?.databaseId); - const container = encodeURIComponent(activeTab?.collection?.id()); - const baseUrl = `vscode://ms-azuretools.vscode-cosmosdb?resourceId=${resourceId}`; - const vscodeUrl = activeTab ? `${baseUrl}&database=${database}&container=${container}` : baseUrl; - return vscodeUrl; - } - - private getVSCodeUrl(): string { - const isvCore = (userContext.apiType || userContext.databaseAccount.kind) === "VCoreMongo"; - return isvCore ? this.getDocumentDbUrl() : this.getCosmosDbUrl(); - } - public openInVsCode(): void { - const vscodeUrl = this.getVSCodeUrl(); + const vscodeUrl = getVSCodeUrl(); const openVSCodeDialogProps: DialogProps = { linkProps: { linkText: "Download Visual Studio Code", diff --git a/src/Utils/VSCodeExtensionUtils.ts b/src/Utils/VSCodeExtensionUtils.ts new file mode 100644 index 000000000..99bb2ac80 --- /dev/null +++ b/src/Utils/VSCodeExtensionUtils.ts @@ -0,0 +1,54 @@ +import { useTabs } from "hooks/useTabs"; +import { userContext } from "UserContext"; +import { getHostFromUrl } from "./../Explorer/Tabs/CloudShellTab/Utils/CommonUtils"; + +export const DOCUMENTDB_VSCODE_EXTENSION_BASEURL = "vscode://ms-azuretools.vscode-documentdb"; +export const COSMOSDB_VSCODE_EXTENSION_BASEURL = "vscode://ms-azuretools.vscode-cosmosdb"; + +/** + * Generates a VS Code DocumentDB connection URL using the current user's MongoDB connection parameters. + * Double-encodes the updated connection string for safe usage in VS Code URLs. + * + * The DocumentDB VS Code extension requires double encoding for connection strings. + * See: https://microsoft.github.io/vscode-documentdb/manual/how-to-construct-url.html#double-encoding + * + * @returns {string} The encoded VS Code DocumentDB connection URL. + */ +export const getVSCodeUrl = (): string => { + const isvCore = (userContext.apiType || userContext.databaseAccount.kind) === "VCoreMongo"; + const isMongo = userContext.apiType === "Mongo"; + return isvCore ? getDocumentDbUrl() : isMongo ? getMongoRUUrl() : getCosmosDbUrl(); +}; + +export const getCosmosDbUrl = () => { + const activeTab = useTabs.getState().activeTab; + const resourceId = encodeURIComponent(userContext.databaseAccount.id); + const database = encodeURIComponent(activeTab?.collection?.databaseId); + const container = encodeURIComponent(activeTab?.collection?.id()); + const baseUrl = `${COSMOSDB_VSCODE_EXTENSION_BASEURL}?resourceId=${resourceId}`; + const vscodeUrl = activeTab ? `${baseUrl}&database=${database}&container=${container}` : baseUrl; + return vscodeUrl; +}; + +export const getMongoRUUrl = () => { + const activeTab = useTabs.getState().activeTab; + const databaseAccount = userContext.databaseAccount; + const host = getHostFromUrl(databaseAccount.properties?.mongoEndpoint); + const port = 10255; + const database = activeTab?.collection?.databaseId; + const container = activeTab?.collection?.id(); + const encodedUpdatedConnectionString = encodeURIComponent(`mongodb://${databaseAccount?.name}@${host}:${port}`); + const documentDbUrl = `${DOCUMENTDB_VSCODE_EXTENSION_BASEURL}?connectionString=${encodedUpdatedConnectionString}${ + database ? `&database=${database}` : "" + }${container ? `&collection=${container}` : ""}`; + + return documentDbUrl; +}; + +export const getDocumentDbUrl = () => { + const { adminLogin: adminLoginuserName = "", connectionString = "" } = userContext.vcoreMongoConnectionParams; + const updatedConnectionString = connectionString.replace(/<(user|username)>:/i, adminLoginuserName); + const encodedUpdatedConnectionString = encodeURIComponent(encodeURIComponent(updatedConnectionString)); + const documentDbUrl = `${DOCUMENTDB_VSCODE_EXTENSION_BASEURL}?connectionString=${encodedUpdatedConnectionString}`; + return documentDbUrl; +};