Compare commits

..

5 Commits

Author SHA1 Message Date
Sung-Hyun Kang
98d7e89712 Added VS Code Exnteion for DE 2025-09-18 08:03:06 -05:00
Sung-Hyun Kang
d45e10f5ac Added VS Code Exnteion for DE 2025-09-18 08:01:01 -05:00
Nishtha Ahuja
cfb5db4df6 Removed screenshot for mongo cloudshell (#2211)
Co-authored-by: nishthaAhujaa <nishtha17354@iiittd.ac.in>
2025-09-16 12:16:19 +05:30
Dmitry Shilov
922ca5c523 chore: Update help link in FabricHome component to point to the new documentation (#2206) 2025-09-04 11:58:07 +02:00
Dmitry Shilov
bafe002fa3 chore: Enhance accessibility (#2208)
- Add tabIndex to button
- Add aria attributes to icons and headings
2025-09-04 11:39:11 +02:00
12 changed files with 116 additions and 149 deletions

View File

@@ -44,6 +44,12 @@ export interface DatabaseAccountExtendedProperties {
publicNetworkAccess?: string; publicNetworkAccess?: string;
enablePriorityBasedExecution?: boolean; enablePriorityBasedExecution?: boolean;
vcoreMongoEndpoint?: string; 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 { export interface DatabaseAccountResponseLocation {

View File

@@ -18,6 +18,7 @@ import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
import { acquireMsalTokenForAccount } from "Utils/AuthorizationUtils"; import { acquireMsalTokenForAccount } from "Utils/AuthorizationUtils";
import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointUtils"; import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointUtils";
import { featureRegistered } from "Utils/FeatureRegistrationUtils"; import { featureRegistered } from "Utils/FeatureRegistrationUtils";
import { getVSCodeUrl } from "Utils/VSCodeExtensionUtils";
import { update } from "Utils/arm/generatedClients/cosmos/databaseAccounts"; import { update } from "Utils/arm/generatedClients/cosmos/databaseAccounts";
import { useQueryCopilot } from "hooks/useQueryCopilot"; import { useQueryCopilot } from "hooks/useQueryCopilot";
import * as ko from "knockout"; 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)>:<password>/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 { public openInVsCode(): void {
const vscodeUrl = this.getVSCodeUrl(); const vscodeUrl = getVSCodeUrl();
const openVSCodeDialogProps: DialogProps = { const openVSCodeDialogProps: DialogProps = {
linkProps: { linkProps: {
linkText: "Download Visual Studio Code", linkText: "Download Visual Studio Code",

View File

@@ -1,8 +1,8 @@
/** /**
* Accordion top class * Accordion top class
*/ */
import { makeStyles, tokens } from "@fluentui/react-components"; import { Link, makeStyles, tokens } from "@fluentui/react-components";
import { DocumentAddRegular, LinkMultipleRegular } from "@fluentui/react-icons"; import { DocumentAddRegular, LinkMultipleRegular, OpenRegular } from "@fluentui/react-icons";
import { SampleDataImportDialog } from "Explorer/SplashScreen/SampleDataImportDialog"; import { SampleDataImportDialog } from "Explorer/SplashScreen/SampleDataImportDialog";
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil"; import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
import { isFabricNative, isFabricNativeReadOnly } from "Platform/Fabric/FabricUtil"; import { isFabricNative, isFabricNativeReadOnly } from "Platform/Fabric/FabricUtil";
@@ -119,7 +119,7 @@ const FabricHomeScreenButton: React.FC<FabricHomeScreenButtonProps & { className
}) => { }) => {
const styles = useStyles(); const styles = useStyles();
return ( return (
<div role="button" className={`${styles.buttonContainer} ${className}`} onClick={onClick}> <div role="button" className={`${styles.buttonContainer} ${className}`} onClick={onClick} tabIndex={0}>
<div className={styles.buttonUpperPart}>{icon}</div> <div className={styles.buttonUpperPart}>{icon}</div>
<div aria-label={title} className={styles.buttonLowerPart}> <div aria-label={title} className={styles.buttonLowerPart}>
<div>{title}</div> <div>{title}</div>
@@ -147,7 +147,7 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
{ {
title: "Sample data", title: "Sample data",
description: "Automatically load sample data in your database", description: "Automatically load sample data in your database",
icon: <img src={CosmosDbBlackIcon} />, icon: <img src={CosmosDbBlackIcon} alt={"Azure Cosmos DB icon"} aria-hidden="true" />,
onClick: () => setOpenSampleDataImportDialog(true), onClick: () => setOpenSampleDataImportDialog(true),
}, },
{ {
@@ -181,16 +181,18 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
explorer={props.explorer} explorer={props.explorer}
databaseName={userContext.fabricContext?.databaseName} databaseName={userContext.fabricContext?.databaseName}
/> />
<div className={styles.title} role="heading" aria-label={title}> <div className={styles.title} role="heading" aria-label={title} aria-level={1}>
{title} {title}
</div> </div>
{getSplashScreenButtons()} {getSplashScreenButtons()}
{/* <div className={styles.footer}> {
Need help?{" "} <div className={styles.footer}>
<Link href="https://aka.ms/cosmosdbfabricdocs" target="_blank"> Need help?{" "}
Learn more <img src={LinkIcon} alt="Learn more" /> <Link href="https://learn.microsoft.com/fabric/database/cosmos-db/overview" target="_blank">
</Link> Learn more <OpenRegular />
</div> */} </Link>
</div>
}
</CosmosFluentProvider> </CosmosFluentProvider>
</> </>
); );

View File

@@ -14,6 +14,11 @@ export const DISABLE_HISTORY = `set +o history`;
* Used when shell initialization or connection fails. * Used when shell initialization or connection fails.
*/ */
export const EXIT_COMMAND = ` printf "\\033[1;31mSession ended. Please close this tab and initiate a new shell session if needed.\\033[0m\\n" && disown -a && exit`; export const EXIT_COMMAND = ` printf "\\033[1;31mSession ended. Please close this tab and initiate a new shell session if needed.\\033[0m\\n" && disown -a && exit`;
/**
* Command that displays error message with MongoDB networking guidance and exits the shell session.
* Used when MongoDB shell connection fails due to networking issues.
*/
export const EXIT_COMMAND_MONGO = ` printf "\\033[1;31mSession ended. Please close this tab and initiate a new shell session if needed.\\033[0m\\n" && printf "\\033[1;36mPlease use the 'Add Azure Cloud Shell IPs' button in the Networking blade to allow Cloud Shell access, if not already configured.\\033[0m\\n" && disown -a && exit`;
/** /**
* This command runs mongosh in no-database and quiet mode, * This command runs mongosh in no-database and quiet mode,
@@ -40,6 +45,14 @@ export abstract class AbstractShellHandler {
abstract getTerminalSuppressedData(): string[]; abstract getTerminalSuppressedData(): string[];
updateTerminalData?(data: string): string; updateTerminalData?(data: string): string;
/**
* Gets the exit command to use when connection fails.
* Can be overridden by subclasses to provide custom exit commands.
*/
protected getExitCommand(): string {
return EXIT_COMMAND;
}
/** /**
* Constructs the complete initialization command sequence for the shell. * Constructs the complete initialization command sequence for the shell.
* *
@@ -64,7 +77,7 @@ export abstract class AbstractShellHandler {
START_MARKER, START_MARKER,
DISABLE_HISTORY, DISABLE_HISTORY,
...setupCommands, ...setupCommands,
`{ ${connectionCommand}; } || true;${EXIT_COMMAND}`, `{ ${connectionCommand}; } || true;${this.getExitCommand()}`,
]; ];
return allCommands.join("\n").concat("\n"); return allCommands.join("\n").concat("\n");

View File

@@ -1,6 +1,6 @@
import { userContext } from "../../../../UserContext"; import { userContext } from "../../../../UserContext";
import { filterAndCleanTerminalOutput, getHostFromUrl, getMongoShellRemoveInfoText } from "../Utils/CommonUtils"; import { filterAndCleanTerminalOutput, getHostFromUrl, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler"; import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
export class MongoShellHandler extends AbstractShellHandler { export class MongoShellHandler extends AbstractShellHandler {
private _key: string; private _key: string;
@@ -48,6 +48,10 @@ export class MongoShellHandler extends AbstractShellHandler {
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."]; return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
} }
protected getExitCommand(): string {
return EXIT_COMMAND_MONGO;
}
updateTerminalData(data: string): string { updateTerminalData(data: string): string {
return filterAndCleanTerminalOutput(data, this._removeInfoText); return filterAndCleanTerminalOutput(data, this._removeInfoText);
} }

View File

@@ -1,6 +1,6 @@
import { userContext } from "../../../../UserContext"; import { userContext } from "../../../../UserContext";
import { filterAndCleanTerminalOutput, getMongoShellRemoveInfoText } from "../Utils/CommonUtils"; import { filterAndCleanTerminalOutput, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler"; import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
export class VCoreMongoShellHandler extends AbstractShellHandler { export class VCoreMongoShellHandler extends AbstractShellHandler {
private _endpoint: string | undefined; private _endpoint: string | undefined;
@@ -35,6 +35,13 @@ export class VCoreMongoShellHandler extends AbstractShellHandler {
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."]; return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
} }
/**
* Override getExitCommand to include MongoDB networking guidance
*/
protected getExitCommand(): string {
return EXIT_COMMAND_MONGO;
}
updateTerminalData(data: string): string { updateTerminalData(data: string): string {
return filterAndCleanTerminalOutput(data, this._removeInfoText); return filterAndCleanTerminalOutput(data, this._removeInfoText);
} }

View File

@@ -1,13 +0,0 @@
export const CLOUDSHELL_IP_RECOMMENDATIONS = {
centralindia: ["4.247.135.109", "74.225.207.63"],
southeastasia: ["4.194.56.6", "4.194.213.10", "4.194.144.127", "4.194.5.74"],
centraluseuap: ["52.158.186.182", "172.215.26.246", "134.138.154.177", "134.138.129.52", "172.215.31.177"],
eastus2euap: ["135.18.43.51", "20.252.175.33", "40.89.88.111", "135.18.17.187", "135.18.67.251"],
eastus: ["40.71.199.151", "20.42.18.188", "52.190.17.9", "20.120.96.152"],
northeurope: ["74.234.65.146", "52.169.70.113"],
southcentralus: ["4.151.247.81", "20.225.211.35", "4.151.48.133", "4.151.247.225"],
westeurope: ["52.166.126.216", "108.142.162.20", "52.178.13.125", "172.201.33.160"],
westus: ["20.245.161.131", "57.154.182.51", "40.118.133.244", "20.253.192.12", "20.43.245.209", "20.66.22.66"],
usgovarizona: ["62.10.232.179"],
usgovvirginia: ["62.10.26.85"],
};

View File

@@ -7,11 +7,8 @@ const validCloudShellRegions = new Set([
"westeurope", "westeurope",
"centralindia", "centralindia",
"southeastasia", "southeastasia",
"westcentralus",
"usgovvirginia", "usgovvirginia",
"usgovarizona", "usgovarizona",
"centraluseuap",
"eastus2euap",
]); ]);
/** /**
@@ -43,8 +40,7 @@ export const getNormalizedRegion = (region: string, defaultCloudshellRegion: str
} }
const regionMap: Record<string, string> = { const regionMap: Record<string, string> = {
centralus: "centraluseuap", eastus2: "eastus",
eastus2: "eastus2euap",
}; };
const normalizedRegion = regionMap[region.toLowerCase()] || region; const normalizedRegion = regionMap[region.toLowerCase()] || region;

View File

@@ -1,40 +0,0 @@
import { configContext } from "ConfigContext";
import * as DataModels from "Contracts/DataModels";
import { userContext } from "UserContext";
import { armRequest } from "Utils/arm/request";
import { CLOUDSHELL_IP_RECOMMENDATIONS } from "../CloudShellTab/Utils/CloudShellIPUtils";
import { getNormalizedRegion } from "../CloudShellTab/Utils/RegionUtils";
export async function checkCloudShellIPsConfigured() {
const databaseRegion = userContext.databaseAccount?.location;
console.log("db region", databaseRegion);
const normalizedRegion = getNormalizedRegion(databaseRegion, "westus");
const cloudShellIPs = getCloudShellIPsForRegion(normalizedRegion);
console.log("CloudShell IPs for region", normalizedRegion, cloudShellIPs);
if (!cloudShellIPs || cloudShellIPs.length === 0) {
return false;
}
const firewallRules = await getFirewallRules();
console.log("firewall rules", firewallRules);
return false;
}
function getCloudShellIPsForRegion(region: string): string[] {
const regionKey = region.toLowerCase();
const ips = CLOUDSHELL_IP_RECOMMENDATIONS[regionKey as keyof typeof CLOUDSHELL_IP_RECOMMENDATIONS];
return ips ? [...ips] : [];
}
async function getFirewallRules(): Promise<DataModels.FirewallRule[]> {
const firewallRulesUri = `${userContext.databaseAccount.id}/firewallRules`;
const response: any = await armRequest({
host: configContext.ARM_ENDPOINT,
path: firewallRulesUri,
method: "GET",
apiVersion: "2023-03-01-preview",
});
return response?.data?.value || response?.value || [];
}

View File

@@ -4,7 +4,6 @@ import { QuickstartFirewallNotification } from "Explorer/Quickstart/QuickstartFi
import { getShellNameForDisplay } from "Explorer/Tabs/CloudShellTab/Utils/CommonUtils"; import { getShellNameForDisplay } from "Explorer/Tabs/CloudShellTab/Utils/CommonUtils";
import * as React from "react"; import * as React from "react";
import FirewallRuleScreenshot from "../../../../images/firewallRule.png"; import FirewallRuleScreenshot from "../../../../images/firewallRule.png";
import VcoreFirewallRuleScreenshot from "../../../../images/vcoreMongoFirewallRule.png";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
@@ -22,28 +21,18 @@ export abstract class BaseTerminalComponentAdapter implements ReactAdapter {
protected getUsername: () => string, protected getUsername: () => string,
protected isAllPublicIPAddressesEnabled: ko.Observable<boolean>, protected isAllPublicIPAddressesEnabled: ko.Observable<boolean>,
protected kind: ViewModels.TerminalKind, protected kind: ViewModels.TerminalKind,
protected isCloudShellIPsConfigured?: ko.Observable<boolean>, ) {}
) { }
public renderComponent(): JSX.Element { public renderComponent(): JSX.Element {
if (this.kind === ViewModels.TerminalKind.VCoreMongo && this.isCloudShellIPsConfigured && !this.isCloudShellIPsConfigured()) { if (this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo) {
return ( return this.renderTerminalComponent();
<QuickstartFirewallNotification
messageType={this.getMessageType()}
screenshot={VcoreFirewallRuleScreenshot}
shellName={getShellNameForDisplay(this.kind)}
/>
);
} }
if (!this.isAllPublicIPAddressesEnabled()) { if (!this.isAllPublicIPAddressesEnabled()) {
return ( return (
<QuickstartFirewallNotification <QuickstartFirewallNotification
messageType={this.getMessageType()} messageType={this.getMessageType()}
screenshot={ screenshot={FirewallRuleScreenshot}
this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo
? VcoreFirewallRuleScreenshot
: FirewallRuleScreenshot
}
shellName={getShellNameForDisplay(this.kind)} shellName={getShellNameForDisplay(this.kind)}
/> />
); );

View File

@@ -8,7 +8,6 @@ import { userContext } from "../../UserContext";
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { useNotebook } from "../Notebook/useNotebook"; import { useNotebook } from "../Notebook/useNotebook";
import { checkCloudShellIPsConfigured } from "./Shared/CloudShellIPChecker";
import { NotebookTerminalComponentAdapter } from "./ShellAdapters/NotebookTerminalComponentAdapter"; import { NotebookTerminalComponentAdapter } from "./ShellAdapters/NotebookTerminalComponentAdapter";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
@@ -24,13 +23,11 @@ export default class TerminalTab extends TabsBase {
private container: Explorer; private container: Explorer;
private notebookTerminalComponentAdapter: ReactAdapter; private notebookTerminalComponentAdapter: ReactAdapter;
private isAllPublicIPAddressesEnabled: ko.Observable<boolean>; private isAllPublicIPAddressesEnabled: ko.Observable<boolean>;
private isCloudShellIPsConfigured: ko.Observable<boolean>;
constructor(options: TerminalTabOptions) { constructor(options: TerminalTabOptions) {
super(options); super(options);
this.container = options.container; this.container = options.container;
this.isAllPublicIPAddressesEnabled = ko.observable(true); this.isAllPublicIPAddressesEnabled = ko.observable(true);
this.isCloudShellIPsConfigured = ko.observable(true);
const commonArgs: [ const commonArgs: [
() => DataModels.DatabaseAccount, () => DataModels.DatabaseAccount,
@@ -39,37 +36,19 @@ export default class TerminalTab extends TabsBase {
ko.Observable<boolean>, ko.Observable<boolean>,
ViewModels.TerminalKind, ViewModels.TerminalKind,
] = [ ] = [
() => userContext?.databaseAccount, () => userContext?.databaseAccount,
() => this.tabId, () => this.tabId,
() => this.getUsername(), () => this.getUsername(),
this.isAllPublicIPAddressesEnabled, this.isAllPublicIPAddressesEnabled,
options.kind, options.kind,
]; ];
if (userContext.features.enableCloudShell) { if (userContext.features.enableCloudShell) {
this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter( this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(...commonArgs);
() => userContext?.databaseAccount,
() => this.tabId,
() => this.getUsername(),
this.isAllPublicIPAddressesEnabled,
options.kind,
options.kind === ViewModels.TerminalKind.VCoreMongo ? this.isCloudShellIPsConfigured : undefined,
);
this.notebookTerminalComponentAdapter.parameters = ko.computed<boolean>(() => { this.notebookTerminalComponentAdapter.parameters = ko.computed<boolean>(() => {
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
const cloudShellConfigured = this.isCloudShellIPsConfigured();
return this.isTemplateReady() && cloudShellConfigured;
}
return this.isTemplateReady() && this.isAllPublicIPAddressesEnabled(); return this.isTemplateReady() && this.isAllPublicIPAddressesEnabled();
}); });
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
(async () => {
const result = await checkCloudShellIPsConfigured();
this.isCloudShellIPsConfigured(result);
})();
}
} else { } else {
this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter( this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter(
() => this.getNotebookServerInfo(options), () => this.getNotebookServerInfo(options),

View File

@@ -0,0 +1,55 @@
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" && userContext.databaseAccount?.properties?.apiProperties?.serverVersion !== "3.2";
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)>:<password>/i, adminLoginuserName);
const encodedUpdatedConnectionString = encodeURIComponent(encodeURIComponent(updatedConnectionString));
const documentDbUrl = `${DOCUMENTDB_VSCODE_EXTENSION_BASEURL}?connectionString=${encodedUpdatedConnectionString}`;
return documentDbUrl;
};