mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-23 10:51:30 +00:00
Compare commits
9 Commits
cja/simple
...
documentdb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98d7e89712 | ||
|
|
d45e10f5ac | ||
|
|
cfb5db4df6 | ||
|
|
922ca5c523 | ||
|
|
bafe002fa3 | ||
|
|
0817acf404 | ||
|
|
8e2c46301d | ||
|
|
012d043c78 | ||
|
|
3afd74a957 |
@@ -144,5 +144,3 @@ __mocks__/monaco-editor.ts
|
||||
src/Explorer/Tree/ResourceTree.tsx
|
||||
src/Utils/EndpointUtils.ts
|
||||
src/Utils/PriorityBasedExecutionUtils.ts
|
||||
|
||||
utils/local-proxy/**
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"EMULATOR_ENDPOINT": "http://localhost:8081"
|
||||
}
|
||||
80
package-lock.json
generated
80
package-lock.json
generated
@@ -205,58 +205,6 @@
|
||||
"webpack-dev-server": "4.15.2"
|
||||
}
|
||||
},
|
||||
"canvas": {
|
||||
"version": "1.0.0",
|
||||
"extraneous": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"local_dependencies/@azure/cosmos": {
|
||||
"version": "4.0.1-beta.3",
|
||||
"extraneous": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^1.0.0",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
"@azure/core-rest-pipeline": "^1.2.0",
|
||||
"@azure/core-tracing": "^1.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"jsbi": "^3.1.3",
|
||||
"node-abort-controller": "^3.0.0",
|
||||
"priorityqueuejs": "^2.0.0",
|
||||
"semaphore": "^1.0.5",
|
||||
"tslib": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0",
|
||||
"uuid": "^8.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"local_dependencies/cosmos": {
|
||||
"name": "@azure/cosmos",
|
||||
"version": "4.0.1-beta.3",
|
||||
"extraneous": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/abort-controller": "^1.0.0",
|
||||
"@azure/core-auth": "^1.3.0",
|
||||
"@azure/core-rest-pipeline": "^1.2.0",
|
||||
"@azure/core-tracing": "^1.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"jsbi": "^3.1.3",
|
||||
"node-abort-controller": "^3.0.0",
|
||||
"priorityqueuejs": "^2.0.0",
|
||||
"semaphore": "^1.0.5",
|
||||
"tslib": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0",
|
||||
"uuid": "^8.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
"version": "1.2.6",
|
||||
"license": "MIT",
|
||||
@@ -7945,7 +7893,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@nteract/data-explorer/node_modules/cross-spawn": {
|
||||
"version": "7.0.5",
|
||||
"version": "6.0.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nice-try": "^1.0.4",
|
||||
@@ -8069,7 +8017,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
@@ -16497,7 +16445,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.5",
|
||||
"version": "7.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
@@ -18411,7 +18359,7 @@
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"ajv": "^6.12.4",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.3.2",
|
||||
"doctrine": "^3.0.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
@@ -18998,7 +18946,7 @@
|
||||
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.0",
|
||||
"human-signals": "^2.1.0",
|
||||
"is-stream": "^2.0.0",
|
||||
@@ -19263,7 +19211,7 @@
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.11.0",
|
||||
"range-parser": "~1.2.1",
|
||||
@@ -19299,7 +19247,7 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/express/node_modules/path-to-regexp": {
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.7",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -30587,7 +30535,7 @@
|
||||
"@yarnpkg/lockfile": "^1.1.0",
|
||||
"chalk": "^4.1.2",
|
||||
"ci-info": "^3.7.0",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"find-yarn-workspace-root": "^2.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"json-stable-stringify": "^1.0.2",
|
||||
@@ -31565,7 +31513,7 @@
|
||||
"address": "^1.1.2",
|
||||
"browserslist": "^4.18.1",
|
||||
"chalk": "^4.1.2",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"detect-port-alt": "^1.1.6",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"filesize": "^8.0.6",
|
||||
@@ -33021,7 +32969,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/sane/node_modules/cross-spawn": {
|
||||
"version": "7.0.5",
|
||||
"version": "6.0.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nice-try": "^1.0.4",
|
||||
@@ -33038,7 +32986,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
@@ -36007,7 +35955,7 @@
|
||||
"@webpack-cli/serve": "^2.0.5",
|
||||
"colorette": "^2.0.14",
|
||||
"commander": "^10.0.1",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"envinfo": "^7.7.3",
|
||||
"fastest-levenshtein": "^1.0.12",
|
||||
"import-local": "^3.0.2",
|
||||
@@ -36532,7 +36480,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/windows-release/node_modules/cross-spawn": {
|
||||
"version": "7.0.5",
|
||||
"version": "6.0.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nice-try": "^1.0.4",
|
||||
@@ -36549,7 +36497,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.5",
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
|
||||
@@ -206,11 +206,9 @@
|
||||
"build:dataExplorer:ci": "npm run build:ci",
|
||||
"build": "npm run format:check && npm run lint && npm run compile && npm run compile:strict && npm run pack:prod && npm run copyToConsumers",
|
||||
"build:ci": "npm run format:check && npm run lint && npm run compile && npm run compile:strict && npm run pack:fast",
|
||||
"build:proxy": "npm run compile && npm run compile:strict && npm run pack:prod && npm run copyToProxy",
|
||||
"pack:prod": "webpack --mode production",
|
||||
"pack:fast": "webpack --mode development --progress",
|
||||
"copyToConsumers": "node copyToConsumers",
|
||||
"copyToProxy": "rm -rf ./utils/local-proxy/dist && cp -r ./dist ./utils/local-proxy",
|
||||
"test": "rimraf coverage && jest",
|
||||
"test:debug": "jest --runInBand",
|
||||
"test:e2e": "jest -c ./jest.config.playwright.js --detectOpenHandles",
|
||||
|
||||
36267
preview/package-lock.json
generated
36267
preview/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -765,3 +765,10 @@ export const ShortenedQueryCopilotSampleContainerSchema = {
|
||||
|
||||
userPrompt: "find all products",
|
||||
};
|
||||
|
||||
export enum MongoGuidRepresentation {
|
||||
Standard = "Standard",
|
||||
CSharpLegacy = "CSharpLegacy",
|
||||
JavaLegacy = "JavaLegacy",
|
||||
PythonLegacy = "PythonLegacy",
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
return authorizationToken;
|
||||
}
|
||||
|
||||
if (configContext.platform === Platform.Emulator || configContext.platform === Platform.VNextEmulator) {
|
||||
if (configContext.platform === Platform.Emulator) {
|
||||
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
|
||||
await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(verb, resourceId, resourceType, headers, EmulatorMasterKey);
|
||||
return decodeURIComponent(headers.authorization);
|
||||
@@ -119,7 +119,7 @@ export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, diagnost
|
||||
};
|
||||
|
||||
export const endpoint = () => {
|
||||
if (configContext.platform === Platform.Emulator || configContext.platform === Platform.VNextEmulator) {
|
||||
if (configContext.platform === Platform.Emulator) {
|
||||
// In worker scope, _global(self).parent does not exist
|
||||
const location = _global.parent ? _global.parent.location : _global.location;
|
||||
return configContext.EMULATOR_ENDPOINT || location.origin;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Constants as CosmosSDKConstants } from "@azure/cosmos";
|
||||
import { getMongoGuidRepresentation } from "Shared/StorageUtility";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
@@ -139,6 +140,9 @@ export function readDocument(
|
||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||
? documentId.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
clientSettings: {
|
||||
guidRepresentation: getMongoGuidRepresentation(),
|
||||
},
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint(configContext.MONGO_PROXY_ENDPOINT);
|
||||
@@ -181,6 +185,9 @@ export function createDocument(
|
||||
partitionKey:
|
||||
collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "",
|
||||
documentContent: JSON.stringify(documentContent),
|
||||
clientSettings: {
|
||||
guidRepresentation: getMongoGuidRepresentation(),
|
||||
},
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint(configContext.MONGO_PROXY_ENDPOINT);
|
||||
@@ -228,6 +235,9 @@ export function updateDocument(
|
||||
? documentId.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
documentContent,
|
||||
clientSettings: {
|
||||
guidRepresentation: getMongoGuidRepresentation(),
|
||||
},
|
||||
};
|
||||
const endpoint = getEndpoint(configContext.MONGO_PROXY_ENDPOINT);
|
||||
|
||||
@@ -274,6 +284,9 @@ export function deleteDocuments(
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
clientSettings: {
|
||||
guidRepresentation: getMongoGuidRepresentation(),
|
||||
},
|
||||
};
|
||||
const endpoint = getEndpoint(configContext.MONGO_PROXY_ENDPOINT);
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ export enum Platform {
|
||||
Hosted = "Hosted",
|
||||
Emulator = "Emulator",
|
||||
Fabric = "Fabric",
|
||||
VNextEmulator = "VNextEmulator",
|
||||
}
|
||||
|
||||
export interface ConfigContext {
|
||||
@@ -216,7 +215,7 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
||||
const AAD_ENDPOINT = params.get("aadEndpoint") || "";
|
||||
updateConfigContext({ AAD_ENDPOINT });
|
||||
}
|
||||
if (params.has("platform") && configContext.platform !== Platform.VNextEmulator) {
|
||||
if (params.has("platform")) {
|
||||
const platform = params.get("platform");
|
||||
switch (platform) {
|
||||
default:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { useDatabases } from "Explorer/useDatabases";
|
||||
import { isFabric, isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
|
||||
import { areAdvancedScriptsSupported } from "Utils/PlatformFeatureUtils";
|
||||
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||
import React from "react";
|
||||
import AddCollectionIcon from "../../images/AddCollection.svg";
|
||||
@@ -131,7 +130,6 @@ export const createCollectionContextMenuButton = (
|
||||
}
|
||||
|
||||
if (
|
||||
areAdvancedScriptsSupported(configContext.platform) &&
|
||||
configContext.platform !== Platform.Fabric &&
|
||||
(userContext.apiType === "SQL" || userContext.apiType === "Gremlin")
|
||||
) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import { useDatabases } from "Explorer/useDatabases";
|
||||
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||
import { isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||
import { isRunningOnPublicCloud } from "Utils/CloudUtils";
|
||||
import { isFeatureSupported, PlatformFeature } from "Utils/PlatformFeatureUtils";
|
||||
import * as React from "react";
|
||||
import DiscardIcon from "../../../../images/discard.svg";
|
||||
import SaveIcon from "../../../../images/save-cosmos.svg";
|
||||
@@ -61,15 +60,15 @@ import {
|
||||
AddMongoIndexProps,
|
||||
ChangeFeedPolicyState,
|
||||
GeospatialConfigType,
|
||||
MongoIndexTypes,
|
||||
SettingsV2TabTypes,
|
||||
TtlType,
|
||||
getMongoNotification,
|
||||
getTabTitle,
|
||||
hasDatabaseSharedThroughput,
|
||||
isDirty,
|
||||
MongoIndexTypes,
|
||||
parseConflictResolutionMode,
|
||||
parseConflictResolutionProcedure,
|
||||
SettingsV2TabTypes,
|
||||
TtlType,
|
||||
} from "./SettingsUtils";
|
||||
|
||||
interface SettingsV2TabInfo {
|
||||
@@ -277,14 +276,14 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
this.saveSettingsButton = {
|
||||
isEnabled: this.isSaveSettingsButtonEnabled,
|
||||
isVisible: () => {
|
||||
return isFeatureSupported(PlatformFeature.UpdateCollection);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
this.discardSettingsChangesButton = {
|
||||
isEnabled: this.isDiscardSettingsButtonEnabled,
|
||||
isVisible: () => {
|
||||
return isFeatureSupported(PlatformFeature.UpdateCollection);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1336,7 +1335,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
});
|
||||
}
|
||||
|
||||
if (isFeatureSupported(PlatformFeature.ComputedProperties) && this.shouldShowComputedPropertiesEditor) {
|
||||
if (this.shouldShowComputedPropertiesEditor) {
|
||||
tabs.push({
|
||||
tab: SettingsV2TabTypes.ComputedPropertiesTab,
|
||||
content: <ComputedPropertiesComponent {...computedPropertiesComponentProps} />,
|
||||
|
||||
@@ -45,7 +45,7 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
|
||||
|
||||
constructor(props: ScaleComponentProps) {
|
||||
super(props);
|
||||
this.isEmulator = configContext.platform === Platform.Emulator || configContext.platform === Platform.VNextEmulator;
|
||||
this.isEmulator = configContext.platform === Platform.Emulator;
|
||||
this.offer = this.props.database?.offer() || this.props.collection?.offer();
|
||||
this.databaseId = this.props.database?.id() || this.props.collection.databaseId;
|
||||
this.collectionId = this.props.collection?.id();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Link } from "@fluentui/react/lib/Link";
|
||||
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
||||
import { Environment, getEnvironment } from "Common/EnvironmentUtility";
|
||||
import { sendMessage } from "Common/MessageHandler";
|
||||
import { configContext, Platform } from "ConfigContext";
|
||||
import { Platform, configContext } from "ConfigContext";
|
||||
import { MessageTypes } from "Contracts/ExplorerContracts";
|
||||
import { useDataPlaneRbac } from "Explorer/Panes/SettingsPane/SettingsPane";
|
||||
import { getCopilotEnabled, isCopilotFeatureRegistered } from "Explorer/QueryCopilot/Shared/QueryCopilotClient";
|
||||
@@ -18,7 +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 { isFeatureSupported, PlatformFeature } from "Utils/PlatformFeatureUtils";
|
||||
import { getVSCodeUrl } from "Utils/VSCodeExtensionUtils";
|
||||
import { update } from "Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import * as ko from "knockout";
|
||||
@@ -290,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 {
|
||||
const vscodeUrl = this.getVSCodeUrl();
|
||||
const vscodeUrl = getVSCodeUrl();
|
||||
const openVSCodeDialogProps: DialogProps = {
|
||||
linkProps: {
|
||||
linkText: "Download Visual Studio Code",
|
||||
@@ -1188,7 +1156,6 @@ export default class Explorer {
|
||||
|
||||
// TODO: remove reference to isNotebookEnabled and isNotebooksEnabledForAccount
|
||||
const isNotebookEnabled =
|
||||
isFeatureSupported(PlatformFeature.Notebooks) &&
|
||||
configContext.platform !== Platform.Fabric &&
|
||||
(userContext.features.notebooksDownBanner ||
|
||||
useNotebook.getState().isPhoenixNotebooks ||
|
||||
@@ -1196,11 +1163,7 @@ export default class Explorer {
|
||||
useNotebook.getState().setIsNotebookEnabled(isNotebookEnabled);
|
||||
useNotebook
|
||||
.getState()
|
||||
.setIsShellEnabled(
|
||||
isFeatureSupported(PlatformFeature.CloudShell) &&
|
||||
useNotebook.getState().isPhoenixFeatures &&
|
||||
isPublicInternetAccessAllowed(),
|
||||
);
|
||||
.setIsShellEnabled(useNotebook.getState().isPhoenixFeatures && isPublicInternetAccessAllowed());
|
||||
|
||||
TelemetryProcessor.trace(Action.NotebookEnabled, ActionModifiers.Mark, {
|
||||
isNotebookEnabled,
|
||||
@@ -1221,7 +1184,6 @@ export default class Explorer {
|
||||
|
||||
public async configureCopilot(): Promise<void> {
|
||||
if (
|
||||
!isFeatureSupported(PlatformFeature.Copilot) ||
|
||||
userContext.apiType !== "SQL" ||
|
||||
!userContext.subscriptionId ||
|
||||
![Environment.Development, Environment.Mpac, Environment.Prod].includes(getEnvironment())
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { KeyboardAction } from "KeyboardShortcuts";
|
||||
import { isDataplaneRbacSupported } from "Utils/APITypeUtils";
|
||||
import { areAdvancedScriptsSupported, isFeatureSupported, PlatformFeature } from "Utils/PlatformFeatureUtils";
|
||||
import * as React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import AddSqlQueryIcon from "../../../../images/AddSqlQuery_16x16.svg";
|
||||
@@ -18,7 +17,7 @@ import SynapseIcon from "../../../../images/synapse-link.svg";
|
||||
import VSCodeIcon from "../../../../images/vscode.svg";
|
||||
import { AuthType } from "../../../AuthType";
|
||||
import * as Constants from "../../../Common/Constants";
|
||||
import { configContext, Platform } from "../../../ConfigContext";
|
||||
import { Platform, configContext } from "../../../ConfigContext";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { userContext } from "../../../UserContext";
|
||||
import { isRunningOnNationalCloud } from "../../../Utils/CloudUtils";
|
||||
@@ -53,7 +52,6 @@ export function createStaticCommandBarButtons(
|
||||
};
|
||||
|
||||
if (
|
||||
isFeatureSupported(PlatformFeature.SynapseLink) &&
|
||||
configContext.platform !== Platform.Fabric &&
|
||||
userContext.apiType !== "Tables" &&
|
||||
userContext.apiType !== "Cassandra"
|
||||
@@ -65,11 +63,9 @@ export function createStaticCommandBarButtons(
|
||||
}
|
||||
if (userContext.apiType !== "Gremlin") {
|
||||
const addVsCode = createOpenVsCodeDialogButton(container);
|
||||
if (addVsCode) {
|
||||
buttons.push(addVsCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDataplaneRbacSupported(userContext.apiType)) {
|
||||
const [loginButtonProps, setLoginButtonProps] = useState<CommandButtonComponentProps | undefined>(undefined);
|
||||
@@ -246,17 +242,11 @@ export function createDivider(): CommandButtonComponentProps {
|
||||
|
||||
function areScriptsSupported(): boolean {
|
||||
return (
|
||||
areAdvancedScriptsSupported() &&
|
||||
configContext.platform !== Platform.Fabric &&
|
||||
(userContext.apiType === "SQL" || userContext.apiType === "Gremlin")
|
||||
configContext.platform !== Platform.Fabric && (userContext.apiType === "SQL" || userContext.apiType === "Gremlin")
|
||||
);
|
||||
}
|
||||
|
||||
function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonComponentProps {
|
||||
if (!isFeatureSupported(PlatformFeature.SynapseLink)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (configContext.platform === Platform.Emulator) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -284,10 +274,6 @@ function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonCo
|
||||
}
|
||||
|
||||
function createOpenVsCodeDialogButton(container: Explorer): CommandButtonComponentProps {
|
||||
if (!isFeatureSupported(PlatformFeature.VSCodeIntegration)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const label = "Visual Studio Code";
|
||||
return {
|
||||
iconSrc: VSCodeIcon,
|
||||
|
||||
@@ -50,7 +50,6 @@ import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||
import { userContext } from "UserContext";
|
||||
import { getCollectionName } from "Utils/APITypeUtils";
|
||||
import { isCapabilityEnabled, isServerlessAccount, isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||
import { isFeatureSupported, PlatformFeature } from "Utils/PlatformFeatureUtils";
|
||||
import { getUpsellMessage } from "Utils/PricingUtils";
|
||||
import { ValidCosmosDbIdDescription, ValidCosmosDbIdInputPattern } from "Utils/ValidationUtils";
|
||||
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
|
||||
@@ -728,7 +727,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
/>
|
||||
)}
|
||||
|
||||
{isFeatureSupported(PlatformFeature.UniqueKeys) && !isFabricNative() && userContext.apiType === "SQL" && (
|
||||
{!isFabricNative() && userContext.apiType === "SQL" && (
|
||||
<Stack style={{ marginTop: -2, marginBottom: -4 }}>
|
||||
{UniqueKeysHeader()}
|
||||
{this.state.uniqueKeys.map((uniqueKey: string, i: number): JSX.Element => {
|
||||
@@ -901,9 +900,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
</CollapsibleSectionComponent>
|
||||
</Stack>
|
||||
)}
|
||||
{isFeatureSupported(PlatformFeature.AdvancedContainerSettings) &&
|
||||
!isFabricNative() &&
|
||||
userContext.apiType !== "Tables" && (
|
||||
{!isFabricNative() && userContext.apiType !== "Tables" && (
|
||||
<CollapsibleSectionComponent
|
||||
title="Advanced"
|
||||
isExpandedByDefault={false}
|
||||
@@ -956,22 +953,16 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
styles={{
|
||||
text: { fontSize: 12 },
|
||||
checkbox: { width: 12, height: 12 },
|
||||
label: {
|
||||
padding: 0,
|
||||
alignItems: "center",
|
||||
wordWrap: "break-word",
|
||||
whiteSpace: "break-spaces",
|
||||
},
|
||||
label: { padding: 0, alignItems: "center", wordWrap: "break-word", whiteSpace: "break-spaces" },
|
||||
}}
|
||||
onChange={(ev: React.FormEvent<HTMLElement>, isChecked: boolean) =>
|
||||
this.setState({ useHashV1: isChecked, subPartitionKeys: [] })
|
||||
}
|
||||
/>
|
||||
<Text variant="small">
|
||||
<Icon iconName="InfoSolid" className="removeIcon" /> To ensure compatibility with older SDKs,
|
||||
the created container will use a legacy partitioning scheme that supports partition key values
|
||||
of size only up to 101 bytes. If this is enabled, you will not be able to use hierarchical
|
||||
partition keys.{" "}
|
||||
<Icon iconName="InfoSolid" className="removeIcon" /> To ensure compatibility with older SDKs, the
|
||||
created container will use a legacy partitioning scheme that supports partition key values of size
|
||||
only up to 101 bytes. If this is enabled, you will not be able to use hierarchical partition keys.{" "}
|
||||
<Link href="https://aka.ms/cosmos-large-pk" target="_blank">
|
||||
Learn more
|
||||
</Link>
|
||||
@@ -1143,10 +1134,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
// }
|
||||
|
||||
private shouldShowCollectionThroughputInput(): boolean {
|
||||
if (!isFeatureSupported(PlatformFeature.ContainerThroughput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isServerlessAccount()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1173,15 +1160,11 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
|
||||
private shouldShowVectorSearchParameters() {
|
||||
return (
|
||||
isFeatureSupported(PlatformFeature.VectorSearch) &&
|
||||
isVectorSearchEnabled() &&
|
||||
(isServerlessAccount() || this.shouldShowCollectionThroughputInput())
|
||||
);
|
||||
return isVectorSearchEnabled() && (isServerlessAccount() || this.shouldShowCollectionThroughputInput());
|
||||
}
|
||||
|
||||
private shouldShowFullTextSearchParameters() {
|
||||
return isFeatureSupported(PlatformFeature.FullTextSearch) && !isFabricNative() && this.showFullTextSearch;
|
||||
return !isFabricNative() && this.showFullTextSearch;
|
||||
}
|
||||
|
||||
private parseUniqueKeys(): DataModels.UniqueKeyPolicy {
|
||||
|
||||
@@ -6,7 +6,6 @@ import { getFullTextLanguageOptions } from "Explorer/Controls/FullTextSeach/Full
|
||||
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||
import React from "react";
|
||||
import { userContext } from "UserContext";
|
||||
import { isFeatureSupported, PlatformFeature } from "Utils/PlatformFeatureUtils";
|
||||
|
||||
export function getPartitionKeyTooltipText(): string {
|
||||
if (userContext.apiType === "Mongo") {
|
||||
@@ -86,11 +85,7 @@ export function UniqueKeysHeader(): JSX.Element {
|
||||
}
|
||||
|
||||
export function shouldShowAnalyticalStoreOptions(): boolean {
|
||||
if (
|
||||
!isFeatureSupported(PlatformFeature.AnalyticalStore) ||
|
||||
isFabricNative() ||
|
||||
configContext.platform === Platform.Emulator
|
||||
) {
|
||||
if (isFabricNative() || configContext.platform === Platform.Emulator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,10 +199,16 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
LocalStorageUtility.getEntryString(StorageKey.CopilotSampleDBEnabled) === "true",
|
||||
);
|
||||
|
||||
const [mongoGuidRepresentation, setMongoGuidRepresentation] = useState<Constants.MongoGuidRepresentation>(
|
||||
LocalStorageUtility.hasItem(StorageKey.MongoGuidRepresentation)
|
||||
? (LocalStorageUtility.getEntryString(StorageKey.MongoGuidRepresentation) as Constants.MongoGuidRepresentation)
|
||||
: Constants.MongoGuidRepresentation.CSharpLegacy,
|
||||
);
|
||||
|
||||
const styles = useStyles();
|
||||
|
||||
const explorerVersion = configContext.gitSha;
|
||||
const isEmulator = configContext.platform === Platform.Emulator || configContext.platform === Platform.VNextEmulator;
|
||||
const isEmulator = configContext.platform === Platform.Emulator;
|
||||
const shouldShowQueryPageOptions = userContext.apiType === "SQL";
|
||||
const showRetrySettings =
|
||||
(userContext.apiType === "SQL" || userContext.apiType === "Tables" || userContext.apiType === "Gremlin") &&
|
||||
@@ -261,6 +267,8 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
useDatabases.getState().sampleDataResourceTokenCollection &&
|
||||
!isEmulator;
|
||||
|
||||
const shouldShowMongoGuidRepresentationOption = userContext.apiType === "Mongo";
|
||||
|
||||
const handlerOnSubmit = async () => {
|
||||
setIsExecuting(true);
|
||||
|
||||
@@ -412,6 +420,10 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldShowMongoGuidRepresentationOption) {
|
||||
LocalStorageUtility.setEntryString(StorageKey.MongoGuidRepresentation, mongoGuidRepresentation);
|
||||
}
|
||||
|
||||
setIsExecuting(false);
|
||||
logConsoleInfo(
|
||||
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`,
|
||||
@@ -433,6 +445,14 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldShowMongoGuidRepresentationOption) {
|
||||
logConsoleInfo(
|
||||
`Updated Mongo Guid Representation to ${LocalStorageUtility.getEntryString(
|
||||
StorageKey.MongoGuidRepresentation,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
refreshExplorer && (await explorer.refreshExplorer());
|
||||
closeSidePanel();
|
||||
};
|
||||
@@ -477,6 +497,13 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
{ key: SplitterDirection.Horizontal, text: "Horizontal" },
|
||||
];
|
||||
|
||||
const mongoGuidRepresentationDropdownOptions: IDropdownOption[] = [
|
||||
{ key: Constants.MongoGuidRepresentation.CSharpLegacy, text: Constants.MongoGuidRepresentation.CSharpLegacy },
|
||||
{ key: Constants.MongoGuidRepresentation.JavaLegacy, text: Constants.MongoGuidRepresentation.JavaLegacy },
|
||||
{ key: Constants.MongoGuidRepresentation.PythonLegacy, text: Constants.MongoGuidRepresentation.PythonLegacy },
|
||||
{ key: Constants.MongoGuidRepresentation.Standard, text: Constants.MongoGuidRepresentation.Standard },
|
||||
];
|
||||
|
||||
const handleOnPriorityLevelOptionChange = (
|
||||
ev: React.FormEvent<HTMLInputElement>,
|
||||
option: IChoiceGroupOption,
|
||||
@@ -559,6 +586,13 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
setRefreshExplorer(false);
|
||||
};
|
||||
|
||||
const handleOnMongoGuidRepresentationOptionChange = (
|
||||
ev: React.FormEvent<HTMLInputElement>,
|
||||
option: IDropdownOption,
|
||||
): void => {
|
||||
setMongoGuidRepresentation(option.key as Constants.MongoGuidRepresentation);
|
||||
};
|
||||
|
||||
const choiceButtonStyles = {
|
||||
root: {
|
||||
clear: "both",
|
||||
@@ -1065,15 +1099,15 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
<div className={styles.settingsSectionContainer}>
|
||||
<div className={styles.settingsSectionDescription}>
|
||||
This is a sample database and collection with synthetic product data you can use to explore using
|
||||
NoSQL queries and Query Advisor. This will appear as another database in the Data Explorer UI, and
|
||||
is created by, and maintained by Microsoft at no cost to you.
|
||||
NoSQL queries. This will appear as another database in the Data Explorer UI, and is created by,
|
||||
and maintained by Microsoft at no cost to you.
|
||||
</div>
|
||||
<Checkbox
|
||||
styles={{
|
||||
label: { padding: 0 },
|
||||
}}
|
||||
className="padding"
|
||||
ariaLabel="Enable sample db for Query Advisor"
|
||||
ariaLabel="Enable sample db for query exploration"
|
||||
checked={copilotSampleDBEnabled}
|
||||
onChange={handleSampleDatabaseChange}
|
||||
label="Enable sample database"
|
||||
@@ -1082,6 +1116,27 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
)}
|
||||
{shouldShowMongoGuidRepresentationOption && (
|
||||
<AccordionItem value="14">
|
||||
<AccordionHeader>
|
||||
<div className={styles.header}>Guid Representation</div>
|
||||
</AccordionHeader>
|
||||
<AccordionPanel>
|
||||
<div className={styles.settingsSectionContainer}>
|
||||
<div className={styles.settingsSectionDescription}>
|
||||
GuidRepresentation in MongoDB refers to how Globally Unique Identifiers (GUIDs) are serialized and
|
||||
deserialized when stored in BSON documents. This will apply to all document operations.
|
||||
</div>
|
||||
<Dropdown
|
||||
aria-labelledby="mongoGuidRepresentation"
|
||||
selectedKey={mongoGuidRepresentation}
|
||||
options={mongoGuidRepresentationDropdownOptions}
|
||||
onChange={handleOnMongoGuidRepresentationOptionChange}
|
||||
/>
|
||||
</div>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
)}
|
||||
</Accordion>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/* eslint-disable no-console */
|
||||
import { Stack } from "@fluentui/react";
|
||||
import { QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
|
||||
import { CommandButtonComponentProps } from "Explorer/Controls/CommandButton/CommandButtonComponent";
|
||||
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
|
||||
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||
import { SaveQueryPane } from "Explorer/Panes/SaveQueryPane/SaveQueryPane";
|
||||
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
|
||||
import { readCopilotToggleStatus, saveCopilotToggleStatus } from "Explorer/QueryCopilot/QueryCopilotUtilities";
|
||||
import { OnExecuteQueryClick } from "Explorer/QueryCopilot/Shared/QueryCopilotClient";
|
||||
import { QueryCopilotProps } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
||||
@@ -13,7 +11,6 @@ import { QueryCopilotResults } from "Explorer/QueryCopilot/Shared/QueryCopilotRe
|
||||
import { userContext } from "UserContext";
|
||||
import { QueryCopilotState, useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import { useSidePanel } from "hooks/useSidePanel";
|
||||
import { ReactTabKind, TabsState, useTabs } from "hooks/useTabs";
|
||||
import React, { useState } from "react";
|
||||
import SplitterLayout from "react-splitter-layout";
|
||||
import QueryCommandIcon from "../../../images/CopilotCommand.svg";
|
||||
@@ -26,7 +23,8 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
|
||||
const [copilotActive, setCopilotActive] = useState<boolean>(() =>
|
||||
readCopilotToggleStatus(userContext.databaseAccount),
|
||||
);
|
||||
const [tabActive, setTabActive] = useState<boolean>(true);
|
||||
//TODO: Uncomment this useState when query copilot is reinstated in DE
|
||||
// const [tabActive, setTabActive] = useState<boolean>(true);
|
||||
|
||||
const getCommandbarButtons = (): CommandButtonComponentProps[] => {
|
||||
const executeQueryBtnLabel = selectedQuery ? "Execute Selection" : "Execute Query";
|
||||
@@ -70,17 +68,18 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
|
||||
useCommandBar.getState().setContextButtons(getCommandbarButtons());
|
||||
}, [query, selectedQuery, copilotActive]);
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => {
|
||||
useTabs.subscribe((state: TabsState) => {
|
||||
if (state.activeReactTab === ReactTabKind.QueryCopilot) {
|
||||
setTabActive(true);
|
||||
} else {
|
||||
setTabActive(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
//TODO: Uncomment this effect when query copilot is reinstated in DE
|
||||
// React.useEffect(() => {
|
||||
// return () => {
|
||||
// useTabs.subscribe((state: TabsState) => {
|
||||
// if (state.activeReactTab === ReactTabKind.QueryCopilot) {
|
||||
// setTabActive(true);
|
||||
// } else {
|
||||
// setTabActive(false);
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
const toggleCopilot = (toggle: boolean) => {
|
||||
setCopilotActive(toggle);
|
||||
@@ -90,6 +89,7 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
|
||||
return (
|
||||
<Stack className="tab-pane" style={{ width: "100%" }}>
|
||||
<div style={isGeneratingQuery ? { height: "100%" } : { overflowY: "auto", height: "100%" }}>
|
||||
{/*TODO: Uncomment this section when query copilot is reinstated in DE
|
||||
{tabActive && copilotActive && (
|
||||
<QueryCopilotPromptbar
|
||||
explorer={explorer}
|
||||
@@ -97,7 +97,7 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
|
||||
databaseId={QueryCopilotSampleDatabaseId}
|
||||
containerId={QueryCopilotSampleContainerId}
|
||||
></QueryCopilotPromptbar>
|
||||
)}
|
||||
)} */}
|
||||
<Stack className="tabPaneContentContainer">
|
||||
<SplitterLayout percentage={true} vertical={true} primaryIndex={0} primaryMinSize={30} secondaryMinSize={70}>
|
||||
<EditorReact
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* Accordion top class
|
||||
*/
|
||||
import { makeStyles, tokens } from "@fluentui/react-components";
|
||||
import { DocumentAddRegular, LinkMultipleRegular } from "@fluentui/react-icons";
|
||||
import { Link, makeStyles, tokens } from "@fluentui/react-components";
|
||||
import { DocumentAddRegular, LinkMultipleRegular, OpenRegular } from "@fluentui/react-icons";
|
||||
import { SampleDataImportDialog } from "Explorer/SplashScreen/SampleDataImportDialog";
|
||||
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
|
||||
import { isFabricNative, isFabricNativeReadOnly } from "Platform/Fabric/FabricUtil";
|
||||
@@ -119,7 +119,7 @@ const FabricHomeScreenButton: React.FC<FabricHomeScreenButtonProps & { className
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
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 aria-label={title} className={styles.buttonLowerPart}>
|
||||
<div>{title}</div>
|
||||
@@ -147,7 +147,7 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
|
||||
{
|
||||
title: "Sample data",
|
||||
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),
|
||||
},
|
||||
{
|
||||
@@ -181,16 +181,18 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
|
||||
explorer={props.explorer}
|
||||
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}
|
||||
</div>
|
||||
{getSplashScreenButtons()}
|
||||
{/* <div className={styles.footer}>
|
||||
{
|
||||
<div className={styles.footer}>
|
||||
Need help?{" "}
|
||||
<Link href="https://aka.ms/cosmosdbfabricdocs" target="_blank">
|
||||
Learn more <img src={LinkIcon} alt="Learn more" />
|
||||
<Link href="https://learn.microsoft.com/fabric/database/cosmos-db/overview" target="_blank">
|
||||
Learn more <OpenRegular />
|
||||
</Link>
|
||||
</div> */}
|
||||
</div>
|
||||
}
|
||||
</CosmosFluentProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||
import * as React from "react";
|
||||
import ConnectIcon from "../../../images/Connect_color.svg";
|
||||
import ContainersIcon from "../../../images/Containers.svg";
|
||||
import CosmosDBIcon from "../../../images/CosmosDB-logo.svg";
|
||||
import LinkIcon from "../../../images/Link_blue.svg";
|
||||
import PowerShellIcon from "../../../images/PowerShell.svg";
|
||||
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
||||
@@ -120,11 +121,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
};
|
||||
|
||||
private getSplashScreenButtons = (): JSX.Element => {
|
||||
if (
|
||||
userContext.apiType === "SQL" &&
|
||||
useQueryCopilot.getState().copilotEnabled &&
|
||||
useDatabases.getState().sampleDataResourceTokenCollection
|
||||
) {
|
||||
if (userContext.apiType === "SQL") {
|
||||
return (
|
||||
<Stack
|
||||
className="splashStackContainer"
|
||||
@@ -152,25 +149,18 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
/>
|
||||
</Stack>
|
||||
<Stack className="splashStackRow" horizontal>
|
||||
{useQueryCopilot.getState().copilotEnabled && (
|
||||
<SplashScreenButton
|
||||
imgSrc={CopilotIcon}
|
||||
title={"Query faster with Query Advisor"}
|
||||
imgSrc={CosmosDBIcon}
|
||||
imgSize={35}
|
||||
title={"Azure Cosmos DB Samples Gallery"}
|
||||
description={
|
||||
"Query Advisor is your AI buddy that helps you write Azure Cosmos DB queries like a pro. Try it using our sample data set now!"
|
||||
"Discover samples that showcase scalable, intelligent app patterns. Try one now to see how fast you can go from concept to code with Cosmos DB"
|
||||
}
|
||||
onClick={() => {
|
||||
const copilotVersion = userContext.features.copilotVersion;
|
||||
if (copilotVersion === "v1.0") {
|
||||
useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot);
|
||||
} else if (copilotVersion === "v2.0") {
|
||||
const sampleCollection = useDatabases.getState().sampleDataResourceTokenCollection;
|
||||
sampleCollection.onNewQueryClick(sampleCollection, undefined);
|
||||
}
|
||||
traceOpen(Action.OpenQueryCopilotFromSplashScreen, { apiType: userContext.apiType });
|
||||
window.open("https://azurecosmosdb.github.io/gallery/?tags=example", "_blank");
|
||||
traceOpen(Action.LearningResourcesClicked, { apiType: userContext.apiType });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SplashScreenButton
|
||||
imgSrc={ConnectIcon}
|
||||
title={"Connect"}
|
||||
@@ -212,6 +202,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
sample data, query.
|
||||
</TeachingBubble>
|
||||
)}
|
||||
{/*TODO: convert below to use SplashScreenButton */}
|
||||
{mainItems.map((item) => (
|
||||
<Stack
|
||||
id={`mainButton-${item.id}`}
|
||||
@@ -477,6 +468,34 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
};
|
||||
}
|
||||
|
||||
//TODO: Re-enable lint rule when query copilot is reinstated in DE
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
private getQueryCopilotCard = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
{useQueryCopilot.getState().copilotEnabled && (
|
||||
<SplashScreenButton
|
||||
imgSrc={CopilotIcon}
|
||||
title={"Query faster with Query Advisor"}
|
||||
description={
|
||||
"Query Advisor is your AI buddy that helps you write Azure Cosmos DB queries like a pro. Try it using our sample data set now!"
|
||||
}
|
||||
onClick={() => {
|
||||
const copilotVersion = userContext.features.copilotVersion;
|
||||
if (copilotVersion === "v1.0") {
|
||||
useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot);
|
||||
} else if (copilotVersion === "v2.0") {
|
||||
const sampleCollection = useDatabases.getState().sampleDataResourceTokenCollection;
|
||||
sampleCollection.onNewQueryClick(sampleCollection, undefined);
|
||||
}
|
||||
traceOpen(Action.OpenQueryCopilotFromSplashScreen, { apiType: userContext.apiType });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
private decorateOpenCollectionActivity({ databaseId, collectionId }: MostRecentActivity.OpenCollectionItem) {
|
||||
return {
|
||||
iconSrc: CollectionIcon,
|
||||
|
||||
@@ -7,6 +7,7 @@ interface SplashScreenButtonProps {
|
||||
title: string;
|
||||
description: string;
|
||||
onClick: () => void;
|
||||
imgSize?: number;
|
||||
}
|
||||
|
||||
export const SplashScreenButton: React.FC<SplashScreenButtonProps> = ({
|
||||
@@ -14,6 +15,7 @@ export const SplashScreenButton: React.FC<SplashScreenButtonProps> = ({
|
||||
title,
|
||||
description,
|
||||
onClick,
|
||||
imgSize,
|
||||
}: SplashScreenButtonProps): JSX.Element => {
|
||||
return (
|
||||
<Stack
|
||||
@@ -39,7 +41,7 @@ export const SplashScreenButton: React.FC<SplashScreenButtonProps> = ({
|
||||
role="button"
|
||||
>
|
||||
<div>
|
||||
<img src={imgSrc} alt={title} aria-hidden="true" />
|
||||
<img src={imgSrc} alt={title} aria-hidden="true" {...(imgSize ? { height: imgSize, width: imgSize } : {})} />
|
||||
</div>
|
||||
<Stack style={{ marginLeft: 16 }}>
|
||||
<Text style={{ fontSize: 18, fontWeight: 600 }}>{title}</Text>
|
||||
|
||||
@@ -22,6 +22,7 @@ import { formatErrorMessage, formatInfoMessage, formatWarningMessage } from "./U
|
||||
|
||||
// Constants
|
||||
const DEFAULT_CLOUDSHELL_REGION = "westus";
|
||||
const DEFAULT_FAIRFAX_CLOUDSHELL_REGION = "usgovvirginia";
|
||||
const POLLING_INTERVAL_MS = 2000;
|
||||
const MAX_RETRY_COUNT = 10;
|
||||
const MAX_PING_COUNT = 120 * 60; // 120 minutes (60 seconds/minute)
|
||||
@@ -153,7 +154,9 @@ export const ensureCloudShellProviderRegistered = async (): Promise<void> => {
|
||||
* Determines the appropriate CloudShell region
|
||||
*/
|
||||
export const determineCloudShellRegion = (): string => {
|
||||
return getNormalizedRegion(userContext.databaseAccount?.location, DEFAULT_CLOUDSHELL_REGION);
|
||||
const defaultRegion =
|
||||
userContext.portalEnv === "fairfax" ? DEFAULT_FAIRFAX_CLOUDSHELL_REGION : DEFAULT_CLOUDSHELL_REGION;
|
||||
return getNormalizedRegion(userContext.databaseAccount?.location, defaultRegion);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,11 @@ export const DISABLE_HISTORY = `set +o history`;
|
||||
* 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`;
|
||||
/**
|
||||
* 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,
|
||||
@@ -40,6 +45,14 @@ export abstract class AbstractShellHandler {
|
||||
abstract getTerminalSuppressedData(): 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.
|
||||
*
|
||||
@@ -64,7 +77,7 @@ export abstract class AbstractShellHandler {
|
||||
START_MARKER,
|
||||
DISABLE_HISTORY,
|
||||
...setupCommands,
|
||||
`{ ${connectionCommand}; } || true;${EXIT_COMMAND}`,
|
||||
`{ ${connectionCommand}; } || true;${this.getExitCommand()}`,
|
||||
];
|
||||
|
||||
return allCommands.join("\n").concat("\n");
|
||||
|
||||
@@ -33,6 +33,7 @@ jest.mock("../../../../UserContext", () => ({
|
||||
}));
|
||||
|
||||
jest.mock("../Utils/CommonUtils", () => ({
|
||||
...jest.requireActual("../Utils/CommonUtils"),
|
||||
getHostFromUrl: jest.fn().mockReturnValue("test-mongo.documents.azure.com"),
|
||||
}));
|
||||
|
||||
@@ -124,7 +125,10 @@ describe("MongoShellHandler", () => {
|
||||
|
||||
describe("getTerminalSuppressedData", () => {
|
||||
it("should return the correct warning message", () => {
|
||||
expect(mongoShellHandler.getTerminalSuppressedData()).toEqual(["Warning: Non-Genuine MongoDB Detected"]);
|
||||
expect(mongoShellHandler.getTerminalSuppressedData()).toEqual([
|
||||
"Warning: Non-Genuine MongoDB Detected",
|
||||
"Telemetry is now disabled.",
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { userContext } from "../../../../UserContext";
|
||||
import { getHostFromUrl } from "../Utils/CommonUtils";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||
import { filterAndCleanTerminalOutput, getHostFromUrl, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
|
||||
|
||||
export class MongoShellHandler extends AbstractShellHandler {
|
||||
private _key: string;
|
||||
private _endpoint: string | undefined;
|
||||
private _removeInfoText: string[] = getMongoShellRemoveInfoText();
|
||||
constructor(private key: string) {
|
||||
super();
|
||||
this._key = key;
|
||||
@@ -44,6 +45,14 @@ export class MongoShellHandler extends AbstractShellHandler {
|
||||
}
|
||||
|
||||
public getTerminalSuppressedData(): string[] {
|
||||
return ["Warning: Non-Genuine MongoDB Detected"];
|
||||
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||
}
|
||||
|
||||
protected getExitCommand(): string {
|
||||
return EXIT_COMMAND_MONGO;
|
||||
}
|
||||
|
||||
updateTerminalData(data: string): string {
|
||||
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { userContext } from "../../../../UserContext";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||
import { filterAndCleanTerminalOutput, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
|
||||
|
||||
export class VCoreMongoShellHandler extends AbstractShellHandler {
|
||||
private _endpoint: string | undefined;
|
||||
private _textFilterRules: string[] = [
|
||||
"For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/",
|
||||
"disableTelemetry() command",
|
||||
"https://www.mongodb.com/legal/privacy-policy",
|
||||
];
|
||||
private _removeInfoText: string[] = getMongoShellRemoveInfoText();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -38,12 +35,14 @@ export class VCoreMongoShellHandler extends AbstractShellHandler {
|
||||
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||
}
|
||||
|
||||
updateTerminalData(content: string): string {
|
||||
const updatedContent = content
|
||||
.split("\n")
|
||||
.filter((line) => !this._textFilterRules.some((part) => line.includes(part)))
|
||||
.filter((line, idx, arr) => (arr.length > 3 && idx <= arr.length - 3 ? !["", "\r"].includes(line) : true)) // Filter out empty lines and carriage returns, but keep the last 3 lines if they exist
|
||||
.join("\n");
|
||||
return updatedContent;
|
||||
/**
|
||||
* Override getExitCommand to include MongoDB networking guidance
|
||||
*/
|
||||
protected getExitCommand(): string {
|
||||
return EXIT_COMMAND_MONGO;
|
||||
}
|
||||
|
||||
updateTerminalData(data: string): string {
|
||||
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,11 @@ export class AttachAddon implements ITerminalAddon {
|
||||
}
|
||||
|
||||
if (this._allowTerminalWrite) {
|
||||
const updatedData = this._shellHandler?.updateTerminalData(data) ?? data;
|
||||
const updatedData =
|
||||
typeof this._shellHandler?.updateTerminalData === "function"
|
||||
? this._shellHandler.updateTerminalData(data)
|
||||
: data;
|
||||
|
||||
const suppressedData = this._shellHandler?.getTerminalSuppressedData();
|
||||
|
||||
const shouldNotWrite = suppressedData.filter(Boolean).some((item) => updatedData.includes(item));
|
||||
|
||||
@@ -50,3 +50,34 @@ export const getShellNameForDisplay = (terminalKind: TerminalKind): string => {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get MongoDB shell information text that should be removed from terminal output
|
||||
*/
|
||||
export const getMongoShellRemoveInfoText = (): string[] => {
|
||||
return [
|
||||
"For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/",
|
||||
"disableTelemetry() command",
|
||||
"https://www.mongodb.com/legal/privacy-policy",
|
||||
];
|
||||
};
|
||||
|
||||
export const filterAndCleanTerminalOutput = (data: string, removeInfoText: string[]): string => {
|
||||
if (!data || removeInfoText.length === 0) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const lines = data.split("\n");
|
||||
const filteredLines: string[] = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const shouldRemove = removeInfoText.some((text) => line.includes(text));
|
||||
|
||||
if (!shouldRemove) {
|
||||
filteredLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredLines.join("\n").replace(/((\r\n)|\n|\r){2,}/g, "\r\n");
|
||||
};
|
||||
|
||||
@@ -7,7 +7,8 @@ const validCloudShellRegions = new Set([
|
||||
"westeurope",
|
||||
"centralindia",
|
||||
"southeastasia",
|
||||
"westcentralus",
|
||||
"usgovvirginia",
|
||||
"usgovarizona",
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -39,7 +40,6 @@ export const getNormalizedRegion = (region: string, defaultCloudshellRegion: str
|
||||
}
|
||||
|
||||
const regionMap: Record<string, string> = {
|
||||
centralus: "westcentralus",
|
||||
eastus2: "eastus",
|
||||
};
|
||||
|
||||
|
||||
@@ -106,6 +106,6 @@ describe("QueryTabComponent", () => {
|
||||
<QueryTabCopilotComponent {...propsMock} />
|
||||
</CopilotProvider>,
|
||||
);
|
||||
expect(container.find(QueryCopilotPromptbar).exists()).toBe(true);
|
||||
expect(container.find(QueryCopilotPromptbar).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ import { useDialog } from "Explorer/Controls/Dialog";
|
||||
import { monaco } from "Explorer/LazyMonaco";
|
||||
import { QueryCopilotFeedbackModal } from "Explorer/QueryCopilot/Modal/QueryCopilotFeedbackModal";
|
||||
import { useCopilotStore } from "Explorer/QueryCopilot/QueryCopilotContext";
|
||||
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
|
||||
import { readCopilotToggleStatus, saveCopilotToggleStatus } from "Explorer/QueryCopilot/QueryCopilotUtilities";
|
||||
import { OnExecuteQueryClick, QueryDocumentsPerPage } from "Explorer/QueryCopilot/Shared/QueryCopilotClient";
|
||||
import { QueryCopilotSidebar } from "Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar";
|
||||
@@ -28,8 +27,9 @@ import { TabsState, useTabs } from "hooks/useTabs";
|
||||
import React, { Fragment, createRef } from "react";
|
||||
import "react-splitter-layout/lib/index.css";
|
||||
import { format } from "react-string-format";
|
||||
import QueryCommandIcon from "../../../../images/CopilotCommand.svg";
|
||||
import LaunchCopilot from "../../../../images/CopilotTabIcon.svg";
|
||||
//TODO: Uncomment next two lines when query copilot is reinstated in DE
|
||||
// import QueryCommandIcon from "../../../../images/CopilotCommand.svg";
|
||||
// import LaunchCopilot from "../../../../images/CopilotTabIcon.svg";
|
||||
import DownloadQueryIcon from "../../../../images/DownloadQuery.svg";
|
||||
import CancelQueryIcon from "../../../../images/Entity_cancel.svg";
|
||||
import ExecuteQueryIcon from "../../../../images/ExecuteQuery.svg";
|
||||
@@ -494,53 +494,55 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.launchCopilotButton.visible && this.isCopilotTabActive) {
|
||||
const mainButtonLabel = "Launch Copilot";
|
||||
const chatPaneLabel = "Open Copilot in chat pane (ALT+C)";
|
||||
const copilotSettingLabel = "Copilot settings";
|
||||
//TODO: Uncomment next section when query copilot is reinstated in DE
|
||||
// if (this.launchCopilotButton.visible && this.isCopilotTabActive) {
|
||||
// const mainButtonLabel = "Launch Copilot";
|
||||
// const chatPaneLabel = "Open Copilot in chat pane (ALT+C)";
|
||||
// const copilotSettingLabel = "Copilot settings";
|
||||
|
||||
const openCopilotChatButton: CommandButtonComponentProps = {
|
||||
iconAlt: chatPaneLabel,
|
||||
onCommandClick: this.launchQueryCopilotChat,
|
||||
commandButtonLabel: chatPaneLabel,
|
||||
ariaLabel: chatPaneLabel,
|
||||
hasPopup: false,
|
||||
};
|
||||
// const openCopilotChatButton: CommandButtonComponentProps = {
|
||||
// iconAlt: chatPaneLabel,
|
||||
// onCommandClick: this.launchQueryCopilotChat,
|
||||
// commandButtonLabel: chatPaneLabel,
|
||||
// ariaLabel: chatPaneLabel,
|
||||
// hasPopup: false,
|
||||
// };
|
||||
|
||||
const copilotSettingsButton: CommandButtonComponentProps = {
|
||||
iconAlt: copilotSettingLabel,
|
||||
onCommandClick: () => undefined,
|
||||
commandButtonLabel: copilotSettingLabel,
|
||||
ariaLabel: copilotSettingLabel,
|
||||
hasPopup: false,
|
||||
};
|
||||
// const copilotSettingsButton: CommandButtonComponentProps = {
|
||||
// iconAlt: copilotSettingLabel,
|
||||
// onCommandClick: () => undefined,
|
||||
// commandButtonLabel: copilotSettingLabel,
|
||||
// ariaLabel: copilotSettingLabel,
|
||||
// hasPopup: false,
|
||||
// };
|
||||
|
||||
const launchCopilotButton: CommandButtonComponentProps = {
|
||||
iconSrc: LaunchCopilot,
|
||||
iconAlt: mainButtonLabel,
|
||||
onCommandClick: this.launchQueryCopilotChat,
|
||||
commandButtonLabel: mainButtonLabel,
|
||||
ariaLabel: mainButtonLabel,
|
||||
hasPopup: false,
|
||||
children: [openCopilotChatButton, copilotSettingsButton],
|
||||
};
|
||||
buttons.push(launchCopilotButton);
|
||||
}
|
||||
// const launchCopilotButton: CommandButtonComponentProps = {
|
||||
// iconSrc: LaunchCopilot,
|
||||
// iconAlt: mainButtonLabel,
|
||||
// onCommandClick: this.launchQueryCopilotChat,
|
||||
// commandButtonLabel: mainButtonLabel,
|
||||
// ariaLabel: mainButtonLabel,
|
||||
// hasPopup: false,
|
||||
// children: [openCopilotChatButton, copilotSettingsButton],
|
||||
// };
|
||||
// buttons.push(launchCopilotButton);
|
||||
// }
|
||||
|
||||
if (this.props.copilotEnabled) {
|
||||
const toggleCopilotButton: CommandButtonComponentProps = {
|
||||
iconSrc: QueryCommandIcon,
|
||||
iconAlt: "Query Advisor",
|
||||
keyboardAction: KeyboardAction.TOGGLE_COPILOT,
|
||||
onCommandClick: () => {
|
||||
this._toggleCopilot(!this.state.copilotActive);
|
||||
},
|
||||
commandButtonLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
|
||||
ariaLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
|
||||
hasPopup: false,
|
||||
};
|
||||
buttons.push(toggleCopilotButton);
|
||||
}
|
||||
//TODO: Uncomment next section when query copilot is reinstated in DE
|
||||
// if (this.props.copilotEnabled) {
|
||||
// const toggleCopilotButton: CommandButtonComponentProps = {
|
||||
// iconSrc: QueryCommandIcon,
|
||||
// iconAlt: "Query Advisor",
|
||||
// keyboardAction: KeyboardAction.TOGGLE_COPILOT,
|
||||
// onCommandClick: () => {
|
||||
// this._toggleCopilot(!this.state.copilotActive);
|
||||
// },
|
||||
// commandButtonLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
|
||||
// ariaLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
|
||||
// hasPopup: false,
|
||||
// };
|
||||
// buttons.push(toggleCopilotButton);
|
||||
// }
|
||||
|
||||
if (!this.props.isPreferredApiMongoDB && this.state.isExecuting) {
|
||||
const label = "Cancel query";
|
||||
@@ -725,6 +727,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
||||
return (
|
||||
<Fragment>
|
||||
<CosmosFluentProvider id={this.props.tabId} className={this.props.styles.queryTab} role="tabpanel">
|
||||
{/*TODO: Uncomment this section when query copilot is reinstated in DE
|
||||
{this.props.copilotEnabled && this.state.currentTabActive && this.state.copilotActive && (
|
||||
<QueryCopilotPromptbar
|
||||
explorer={this.props.collection.container}
|
||||
@@ -732,7 +735,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
||||
databaseId={this.props.collection.databaseId}
|
||||
containerId={this.props.collection.id()}
|
||||
></QueryCopilotPromptbar>
|
||||
)}
|
||||
)} */}
|
||||
{/* Set 'key' to the value of vertical to force re-rendering when vertical changes, to work around https://github.com/johnwalley/allotment/issues/457 */}
|
||||
<Allotment
|
||||
key={vertical.toString()}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { QuickstartFirewallNotification } from "Explorer/Quickstart/QuickstartFi
|
||||
import { getShellNameForDisplay } from "Explorer/Tabs/CloudShellTab/Utils/CommonUtils";
|
||||
import * as React from "react";
|
||||
import FirewallRuleScreenshot from "../../../../images/firewallRule.png";
|
||||
import VcoreFirewallRuleScreenshot from "../../../../images/vcoreMongoFirewallRule.png";
|
||||
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
@@ -25,15 +24,15 @@ export abstract class BaseTerminalComponentAdapter implements ReactAdapter {
|
||||
) {}
|
||||
|
||||
public renderComponent(): JSX.Element {
|
||||
if (this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo) {
|
||||
return this.renderTerminalComponent();
|
||||
}
|
||||
|
||||
if (!this.isAllPublicIPAddressesEnabled()) {
|
||||
return (
|
||||
<QuickstartFirewallNotification
|
||||
messageType={this.getMessageType()}
|
||||
screenshot={
|
||||
this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo
|
||||
? VcoreFirewallRuleScreenshot
|
||||
: FirewallRuleScreenshot
|
||||
}
|
||||
screenshot={FirewallRuleScreenshot}
|
||||
shellName={getShellNameForDisplay(this.kind)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -21,12 +21,7 @@ import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter";
|
||||
import { useSelectedNode } from "../useSelectedNode";
|
||||
|
||||
export const shouldShowScriptNodes = (): boolean => {
|
||||
return (
|
||||
!isFabric() &&
|
||||
configContext.platform !== Platform.Emulator &&
|
||||
configContext.platform !== Platform.VNextEmulator &&
|
||||
(userContext.apiType === "SQL" || userContext.apiType === "Gremlin")
|
||||
);
|
||||
return !isFabric() && (userContext.apiType === "SQL" || userContext.apiType === "Gremlin");
|
||||
};
|
||||
|
||||
const TreeDatabaseIcon = <DatabaseRegular fontSize={16} />;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MongoGuidRepresentation } from "Common/Constants";
|
||||
import { SplitterDirection } from "Common/Splitter";
|
||||
import * as LocalStorageUtility from "./LocalStorageUtility";
|
||||
import * as SessionStorageUtility from "./SessionStorageUtility";
|
||||
@@ -33,6 +34,7 @@ export enum StorageKey {
|
||||
DocumentsTabPrefs,
|
||||
DefaultQueryResultsView,
|
||||
AppState,
|
||||
MongoGuidRepresentation,
|
||||
}
|
||||
|
||||
export const hasRUThresholdBeenConfigured = (): boolean => {
|
||||
@@ -65,4 +67,13 @@ export const getDefaultQueryResultsView = (): SplitterDirection => {
|
||||
return SplitterDirection.Horizontal;
|
||||
};
|
||||
|
||||
export const getMongoGuidRepresentation = (): MongoGuidRepresentation => {
|
||||
const mongoGuidRepresentation: string | null = LocalStorageUtility.getEntryString(StorageKey.MongoGuidRepresentation);
|
||||
if (mongoGuidRepresentation) {
|
||||
return mongoGuidRepresentation as MongoGuidRepresentation;
|
||||
}
|
||||
|
||||
return MongoGuidRepresentation.CSharpLegacy;
|
||||
};
|
||||
|
||||
export const DefaultRUThreshold = 5000;
|
||||
|
||||
@@ -79,22 +79,7 @@ export const defaultAllowedCassandraProxyEndpoints: ReadonlyArray<string> = [
|
||||
CassandraProxyEndpoints.Mooncake,
|
||||
];
|
||||
|
||||
export const allowedCassandraProxyEndpoints_ToBeDeprecated: ReadonlyArray<string> = [
|
||||
"https://main.documentdb.ext.azure.com",
|
||||
"https://main.documentdb.ext.azure.cn",
|
||||
"https://main.documentdb.ext.azure.us",
|
||||
"https://main.cosmos.ext.azure",
|
||||
"https://localhost:12901",
|
||||
];
|
||||
|
||||
export const CassandraProxyOutboundIPs: { [key: string]: string[] } = {
|
||||
[CassandraProxyEndpoints.Mpac]: ["40.113.96.14", "104.42.11.145"],
|
||||
[CassandraProxyEndpoints.Prod]: ["137.117.230.240", "168.61.72.237"],
|
||||
[CassandraProxyEndpoints.Fairfax]: ["52.244.50.101", "52.227.165.24"],
|
||||
[CassandraProxyEndpoints.Mooncake]: ["40.73.99.146", "143.64.62.47"],
|
||||
};
|
||||
|
||||
export const allowedEmulatorEndpoints: ReadonlyArray<string> = ["https://localhost:8081", "http://localhost:8081"];
|
||||
export const allowedEmulatorEndpoints: ReadonlyArray<string> = ["https://localhost:8081"];
|
||||
|
||||
export const allowedArcadiaEndpoints: ReadonlyArray<string> = ["https://workspaceartifacts.projectarcadia.net"];
|
||||
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import { Platform, configContext } from "../ConfigContext";
|
||||
|
||||
/**
|
||||
* Feature flags enumeration - centralized feature definitions
|
||||
*/
|
||||
export enum PlatformFeature {
|
||||
// UI/Core Features
|
||||
Queries = "Queries",
|
||||
Notebooks = "Notebooks",
|
||||
SynapseLink = "SynapseLink",
|
||||
VSCodeIntegration = "VSCodeIntegration",
|
||||
GlobalSecondaryIndex = "GlobalSecondaryIndex",
|
||||
DataPlaneRbac = "DataPlaneRbac",
|
||||
EntraIDLogin = "EntraIDLogin",
|
||||
EntreIDRbac = "EntreIDRbac",
|
||||
RetrySettings = "RetrySettings",
|
||||
GraphAutoVizOption = "GraphAutoVizOption",
|
||||
CrossPartitionOption = "CrossPartitionOption",
|
||||
EnhancedQueryControl = "EnhancedQueryControl",
|
||||
ParallelismOption = "ParallelismOption",
|
||||
EnableEntraIdRbac = "EnableEntraIdRbac",
|
||||
PriorityBasedExecution = "PriorityBasedExecution",
|
||||
RegionSelection = "RegionSelection",
|
||||
Copilot = "Copilot",
|
||||
CloudShell = "CloudShell",
|
||||
ContainerPagination = "ContainerPagination",
|
||||
FullTextSearch = "FullTextSearch",
|
||||
VectorSearch = "VectorSearch",
|
||||
ThroughputBucketing = "ThroughputBucketing",
|
||||
ComputedProperties = "ComputedProperties",
|
||||
AnalyticalStore = "AnalyticalStore",
|
||||
UniqueKeys = "UniqueKeys",
|
||||
ContainerThroughput = "ContainerThroughput",
|
||||
AdvancedContainerSettings = "AdvancedContainerSettings",
|
||||
|
||||
// CRUD Operations - Database
|
||||
CreateDatabase = "CreateDatabase",
|
||||
ReadDatabase = "ReadDatabase",
|
||||
DeleteDatabase = "DeleteDatabase",
|
||||
|
||||
// CRUD Operations - Collection
|
||||
CreateCollection = "CreateCollection",
|
||||
ReadCollection = "ReadCollection",
|
||||
UpdateCollection = "UpdateCollection",
|
||||
DeleteCollection = "DeleteCollection",
|
||||
|
||||
// CRUD Operations - Document
|
||||
CreateDocument = "CreateDocument",
|
||||
ReadDocument = "ReadDocument",
|
||||
UpdateDocument = "UpdateDocument",
|
||||
DeleteDocument = "DeleteDocument",
|
||||
|
||||
// Advanced Database Features
|
||||
StoredProcedures = "StoredProcedures",
|
||||
UDF = "UDF",
|
||||
Trigger = "Trigger",
|
||||
}
|
||||
|
||||
/**
|
||||
* Feature matrix per platform.
|
||||
* - Only list platforms that have restrictions. If a platform is not present, all features are considered supported.
|
||||
* - Start with VNextEmulator today; add more platforms/flags here later without touching calling code.
|
||||
*/
|
||||
const FEATURE_MATRIX: ReadonlyMap<Platform, ReadonlySet<PlatformFeature>> = new Map([
|
||||
[
|
||||
Platform.VNextEmulator,
|
||||
new Set<PlatformFeature>([
|
||||
PlatformFeature.Queries,
|
||||
PlatformFeature.UniqueKeys,
|
||||
|
||||
PlatformFeature.CreateDatabase,
|
||||
PlatformFeature.ReadDatabase,
|
||||
PlatformFeature.DeleteDatabase,
|
||||
|
||||
PlatformFeature.CreateCollection,
|
||||
PlatformFeature.ReadCollection,
|
||||
PlatformFeature.UpdateCollection,
|
||||
PlatformFeature.DeleteCollection,
|
||||
|
||||
PlatformFeature.CreateDocument,
|
||||
PlatformFeature.ReadDocument,
|
||||
PlatformFeature.UpdateDocument,
|
||||
PlatformFeature.DeleteDocument,
|
||||
]),
|
||||
],
|
||||
]);
|
||||
|
||||
/**
|
||||
* Central feature flag function - checks if a feature is enabled for current platform
|
||||
* @param feature The feature to check
|
||||
* @param platform Optional platform override, defaults to current platform
|
||||
* @returns True if the feature is enabled for the platform, false otherwise
|
||||
*/
|
||||
export const isFeatureSupported = (feature: PlatformFeature, platform?: Platform): boolean => {
|
||||
const currentPlatform = platform ?? configContext.platform;
|
||||
if (currentPlatform !== Platform.VNextEmulator) {
|
||||
return true;
|
||||
}
|
||||
// VNextEmulator: check from the feature matrix
|
||||
const vnextFeatures = FEATURE_MATRIX.get(Platform.VNextEmulator);
|
||||
return vnextFeatures?.has(feature) ?? false;
|
||||
};
|
||||
|
||||
export const areAdvancedScriptsSupported = (platform?: Platform): boolean => {
|
||||
const currentPlatform = platform ?? configContext.platform;
|
||||
if (currentPlatform !== Platform.VNextEmulator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, require all script features to be enabled
|
||||
return (
|
||||
isFeatureSupported(PlatformFeature.StoredProcedures, currentPlatform) &&
|
||||
isFeatureSupported(PlatformFeature.UDF, currentPlatform) &&
|
||||
isFeatureSupported(PlatformFeature.Trigger, currentPlatform)
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import { PartitionKey, PartitionKeyDefinition } from "@azure/cosmos";
|
||||
import { configContext, Platform } from "ConfigContext";
|
||||
import { getRUThreshold, ruThresholdEnabled } from "Shared/StorageUtility";
|
||||
import { userContext } from "UserContext";
|
||||
import { logConsoleWarning } from "Utils/NotificationConsoleUtils";
|
||||
@@ -67,11 +66,7 @@ export function buildDocumentsQueryPartitionProjections(
|
||||
}
|
||||
});
|
||||
const fullAccess = `${collectionAlias}${projectedProperty}`;
|
||||
if (
|
||||
!isSystemPartitionKey &&
|
||||
configContext.platform !== Platform.Emulator &&
|
||||
configContext.platform !== Platform.VNextEmulator
|
||||
) {
|
||||
if (!isSystemPartitionKey) {
|
||||
const wrappedProjection = `IIF(IS_DEFINED(${fullAccess}), ${fullAccess}, {})`;
|
||||
projections.push(wrappedProjection);
|
||||
} else {
|
||||
|
||||
55
src/Utils/VSCodeExtensionUtils.ts
Normal file
55
src/Utils/VSCodeExtensionUtils.ts
Normal 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;
|
||||
};
|
||||
@@ -86,7 +86,7 @@ export function useKnockoutExplorer(platform: Platform): Explorer {
|
||||
let explorer: Explorer;
|
||||
if (platform === Platform.Hosted) {
|
||||
explorer = await configureHosted();
|
||||
} else if (platform === Platform.Emulator || platform === Platform.VNextEmulator) {
|
||||
} else if (platform === Platform.Emulator) {
|
||||
explorer = configureEmulator();
|
||||
} else if (platform === Platform.Portal) {
|
||||
explorer = await configurePortal();
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Azure Cosmos DB Emulator</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="divQuickStart">
|
||||
<div class="Introlines">
|
||||
<p class="Introline1">Congratulations! Your Azure Cosmos DB emulator is running.</p>
|
||||
<p class="Introline2">Now, let's connect a sample app to it.</p>
|
||||
<div id="divQuickStartConnections">
|
||||
<p class="Introline2">URI</p>
|
||||
<input type="text" class="codeblock" readonly="readonly" value="http://localhost:8081" />
|
||||
<p class="Introline2">Primary Key</p>
|
||||
<input
|
||||
type="text"
|
||||
class="codeblock"
|
||||
readonly="readonly"
|
||||
value="C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
|
||||
/>
|
||||
<p class="Introline2">Primary Connection String</p>
|
||||
<input
|
||||
type="text"
|
||||
class="codeblock"
|
||||
readonly="readonly"
|
||||
value="AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
|
||||
/>
|
||||
</div>
|
||||
<p class="Introline3"><b>Choose a platform</b></p>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<ul class="nav nav-tabs qslevel">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" href="#net">
|
||||
<img class="qsmenuicons" src="../images/dotnet.png" alt=".NET" /> .NET
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#java"> <img class="qsmenuicons" src="../images/java.png" alt="Java" /> Java </a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#nodejs">
|
||||
<img class="qsmenuicons" src="../images/nodejs.png" alt="Node.js" /> Node.js
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#python">
|
||||
<img class="qsmenuicons" src="../images/python.png" alt="Python" /> Python
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#go"> <img class="qsmenuicons" src="../images/golang.svg" alt="Go" /> Go </a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#springboot">
|
||||
<img class="qsmenuicons" src="../images/springboot.svg" alt="Spring Boot" /> Spring Boot
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div id="net" class="tab-pane fade in active">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new .NET app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet" target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new .NET app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="java" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Java app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-java" target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new Java app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="nodejs" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Node.js app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-nodejs?pivots=programming-language-ts"
|
||||
target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new Node.js app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="python" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Python app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://aka.ms/cosmos-db-emulator/tutorial/python" target="_blank">tutorial</a>
|
||||
to create a new Python app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="go" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Go app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-go" target="_blank">tutorial</a>
|
||||
to create a new Go app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="springboot" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Spring Boot app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/tutorial-springboot-azure-kubernetes-service"
|
||||
target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new Spring Boot app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="learnMoreTpl">
|
||||
<div class="app-block">
|
||||
<div class="numbersize">2</div>
|
||||
<div class="numberheading">
|
||||
Learn more about Azure Cosmos DB
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://azurecosmosdb.github.io/gallery/?tags=example" target="_blank" class="atags"
|
||||
>Code Samples</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/docs" target="_blank" class="atags">Documentation</a></li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/pricing" target="_blank" class="atags">Pricing</a></li>
|
||||
<li>
|
||||
<a href="https://cosmos.azure.com/capacitycalculator/" target="_blank" class="atags">Capacity planner</a>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/stackoverflow" target="_blank" class="atags">Forum</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll(".learn-more").forEach((slot) => {
|
||||
const node = document.getElementById("learnMoreTpl").content.cloneNode(true);
|
||||
slot.appendChild(node);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,200 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Azure Cosmos DB Emulator</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="divQuickStart">
|
||||
<div class="Introlines">
|
||||
<p class="Introline1">Congratulations! Your Azure Cosmos DB emulator is running.</p>
|
||||
<p class="Introline2">Now, let's connect a sample app to it.</p>
|
||||
<div id="divQuickStartConnections">
|
||||
<p class="Introline2">URI</p>
|
||||
<input type="text" class="codeblock" readonly="readonly" value="https://localhost:8081" />
|
||||
<p class="Introline2">Primary Key</p>
|
||||
<input
|
||||
type="text"
|
||||
class="codeblock"
|
||||
readonly="readonly"
|
||||
value="C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
|
||||
/>
|
||||
<p class="Introline2">Primary Connection String</p>
|
||||
<input
|
||||
type="text"
|
||||
class="codeblock"
|
||||
readonly="readonly"
|
||||
value="AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
|
||||
/>
|
||||
</div>
|
||||
<p class="Introline3"><b>Choose a platform</b></p>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<ul class="nav nav-tabs qslevel">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" href="#net">
|
||||
<img class="qsmenuicons" src="../images/dotnet.png" alt=".NET" /> .NET
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#java"> <img class="qsmenuicons" src="../images/java.png" alt="Java" /> Java </a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#nodejs">
|
||||
<img class="qsmenuicons" src="../images/nodejs.png" alt="Node.js" /> Node.js
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#python">
|
||||
<img class="qsmenuicons" src="../images/python.png" alt="Python" /> Python
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#go"> <img class="qsmenuicons" src="../images/golang.svg" alt="Go" /> Go </a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#springboot">
|
||||
<img class="qsmenuicons" src="../images/springboot.svg" alt="Spring Boot" /> Spring Boot
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div id="net" class="tab-pane fade in active">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new .NET app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet" target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new .NET app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="java" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Java app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-java" target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new Java app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="nodejs" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Node.js app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-nodejs?pivots=programming-language-ts"
|
||||
target="_blank"
|
||||
>tutorial
|
||||
</a>
|
||||
to create a new Node.js app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="python" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Python app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://aka.ms/cosmos-db-emulator/tutorial/python" target="_blank">tutorial</a>
|
||||
to create a new Python app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="go" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Go app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-go" target="_blank">tutorial</a>
|
||||
to create a new Go app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
|
||||
<div id="springboot" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Spring Boot app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/tutorial-springboot-azure-kubernetes-service"
|
||||
target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new Spring Boot app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="learnMoreTpl">
|
||||
<div class="app-block">
|
||||
<div class="numbersize">2</div>
|
||||
<div class="numberheading">
|
||||
Learn more about Azure Cosmos DB
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://azurecosmosdb.github.io/gallery/?tags=example" target="_blank" class="atags"
|
||||
>Code Samples</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/docs" target="_blank" class="atags">Documentation</a></li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/pricing" target="_blank" class="atags">Pricing</a></li>
|
||||
<li>
|
||||
<a href="https://cosmos.azure.com/capacitycalculator/" target="_blank" class="atags">Capacity planner</a>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/stackoverflow" target="_blank" class="atags">Forum</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll(".learn-more").forEach((slot) => {
|
||||
const node = document.getElementById("learnMoreTpl").content.cloneNode(true);
|
||||
slot.appendChild(node);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,179 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
|
||||
<title>Azure Cosmos DB Emulator (SQL)</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="divQuickStart">
|
||||
<div class="Introlines">
|
||||
<p class="Introline1">Congratulations! Your Azure Cosmos DB emulator is running.</p>
|
||||
<p class="Introline2">Now, let's connect a sample app to it.</p>
|
||||
<div id="divQuickStartConnections">
|
||||
<p class="Introline2">URI</p>
|
||||
<input type="text" class="codeblock" readonly value="<%= endpointUri %>" />
|
||||
<p class="Introline2">Primary Key</p>
|
||||
<input type="text" class="codeblock" readonly value="<%= primaryKey %>" />
|
||||
<p class="Introline2">Primary Connection String</p>
|
||||
<input type="text" class="codeblock" readonly value="<%= primaryConnString %>" />
|
||||
</div>
|
||||
<p class="Introline3"><b>Choose a platform</b></p>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<ul class="nav nav-tabs qslevel">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" href="#net"> <img class="qsmenuicons" src="images/dotnet.png" alt=".NET" /> .NET </a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#java"><img class="qsmenuicons" src="images/java.png" alt="Java" /> Java</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#nodejs"
|
||||
><img class="qsmenuicons" src="images/nodejs.png" alt="Node.js" /> Node.js</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#python"
|
||||
><img class="qsmenuicons" src="images/python.png" alt="Python" /> Python</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#go"><img class="qsmenuicons" src="images/golang.svg" alt="Go" /> Go</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-toggle="tab" href="#springboot"
|
||||
><img class="qsmenuicons" src="images/springboot.svg" alt="Spring Boot" /> Spring Boot</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="net" class="tab-pane fade in active">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new .NET app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet" target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new .NET app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
<div id="java" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Java app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-java" target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new Java app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
<div id="nodejs" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Node.js app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-nodejs?pivots=programming-language-ts"
|
||||
target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new Node.js app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
<div id="python" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Python app
|
||||
<p>
|
||||
Follow this <a href="https://aka.ms/cosmos-db-emulator/tutorial/python" target="_blank">tutorial</a>
|
||||
to create a new Python app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
<div id="go" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Go app
|
||||
<p>
|
||||
Follow this
|
||||
<a href="https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-go" target="_blank">tutorial</a>
|
||||
to create a new Go app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
<div id="springboot" class="tab-pane fade">
|
||||
<div class="sampleApp">
|
||||
<div class="numbersize numbersizePadding">1</div>
|
||||
<div class="numberheading">
|
||||
Create a new Spring Boot app
|
||||
<p>
|
||||
Follow this
|
||||
<a
|
||||
href="https://learn.microsoft.com/azure/cosmos-db/nosql/tutorial-springboot-azure-kubernetes-service"
|
||||
target="_blank"
|
||||
>tutorial</a
|
||||
>
|
||||
to create a new Spring Boot app connected to Azure Cosmos DB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="learn-more"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="learnMoreTpl">
|
||||
<div class="app-block">
|
||||
<div class="numbersize">2</div>
|
||||
<div class="numberheading">
|
||||
Learn more about Azure Cosmos DB
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://azurecosmosdb.github.io/gallery/?tags=example" target="_blank" class="atags"
|
||||
>Code Samples</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/docs" target="_blank" class="atags">Documentation</a></li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/pricing" target="_blank" class="atags">Pricing</a></li>
|
||||
<li>
|
||||
<a href="https://cosmos.azure.com/capacitycalculator/" target="_blank" class="atags">Capacity planner</a>
|
||||
</li>
|
||||
<li><a href="https://aka.ms/cosmos-db-emulator/stackoverflow" target="_blank" class="atags">Forum</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll(".learn-more").forEach((slot) => {
|
||||
const node = document.getElementById("learnMoreTpl").content.cloneNode(true);
|
||||
slot.appendChild(node);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -15,12 +15,18 @@
|
||||
"target": "es2017",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"lib": ["es5", "es6", "dom"],
|
||||
"lib": [
|
||||
"es5",
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"jsx": "react",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true,
|
||||
"types": ["jest"],
|
||||
"types": [
|
||||
"jest"
|
||||
],
|
||||
"baseUrl": "src"
|
||||
},
|
||||
"typedocOptions": {
|
||||
@@ -37,8 +43,14 @@
|
||||
"includes": "./src/SelfServe/Documentation",
|
||||
"disableSources": true
|
||||
},
|
||||
"include": ["src", "./src/**/*", "./utils/**/*"],
|
||||
"exclude": ["./src/**/__mocks__/**/*", "./utils/local-proxy/**/*"],
|
||||
"include": [
|
||||
"src",
|
||||
"./src/**/*",
|
||||
"./utils/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"./src/**/__mocks__/**/*"
|
||||
],
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS"
|
||||
|
||||
6
utils/local-proxy/.gitignore
vendored
6
utils/local-proxy/.gitignore
vendored
@@ -1,6 +0,0 @@
|
||||
dist*
|
||||
node_modules
|
||||
*.cert
|
||||
*.key
|
||||
*.pfx
|
||||
*.log
|
||||
@@ -1,177 +0,0 @@
|
||||
const express = require("express");
|
||||
const { createProxyMiddleware } = require("http-proxy-middleware");
|
||||
const { inspect } = require("util");
|
||||
const fs = require("fs");
|
||||
const https = require("https");
|
||||
|
||||
const conf = {};
|
||||
conf.PORT = process.env.EXPLORER_PORT || 1234;
|
||||
conf.LOG_LEVEL = process.env.LOG_LEVEL || "info";
|
||||
conf.EMULATOR_ENDPOINT = process.env.EMULATOR_ENDPOINT || "http://localhost:8081";
|
||||
conf.ENDPOINT_DISCOVERY_ENABLED = (process.env.ENDPOINT_DISCOVERY_ENABLED || "false").toLowerCase() === "true";
|
||||
conf.GATEWAY_TLS_ENABLED = (process.env.GATEWAY_TLS_ENABLED || "false").toLowerCase() === "true";
|
||||
conf.CERT_PATH = process.env.CERT_PATH;
|
||||
conf.CERT_SECRET = process.env.CERT_SECRET;
|
||||
|
||||
const LOG_NUM = levelToNumber(conf.LOG_LEVEL);
|
||||
function _log(level, msg, color) {
|
||||
if (levelToNumber(level) >= LOG_NUM) {
|
||||
console.log(`${colorToCode(color)}[${level || "debug"}]${msg}\x1b[0m`);
|
||||
}
|
||||
}
|
||||
|
||||
function _debug(msg, color) {
|
||||
_log("debug", msg, color);
|
||||
}
|
||||
|
||||
function _info(msg, color) {
|
||||
_log("info", msg, color);
|
||||
}
|
||||
|
||||
function _warn(msg, color) {
|
||||
_log("warn", msg, color || "yellow");
|
||||
}
|
||||
|
||||
function _err(msg, color) {
|
||||
_log("error", msg, color || "red");
|
||||
}
|
||||
|
||||
function levelToNumber(level) {
|
||||
switch (level) {
|
||||
case "debug":
|
||||
return 0;
|
||||
case "info":
|
||||
return 1;
|
||||
case "warn":
|
||||
return 2;
|
||||
case "error":
|
||||
return 3;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function colorToCode(color) {
|
||||
switch (color) {
|
||||
case "red":
|
||||
return "\x1b[31m";
|
||||
case "green":
|
||||
return "\x1b[32m";
|
||||
case "blue":
|
||||
return "\x1b[34m";
|
||||
case "yellow":
|
||||
return "\x1b[33m";
|
||||
default:
|
||||
return "\x1b[0m";
|
||||
}
|
||||
}
|
||||
|
||||
function statusToColor(status) {
|
||||
if (status < 300) {
|
||||
return "green";
|
||||
} else if (status < 400) {
|
||||
return "blue";
|
||||
} else {
|
||||
return "red";
|
||||
}
|
||||
}
|
||||
|
||||
const testEndpoint = () => {
|
||||
fetch(conf.EMULATOR_ENDPOINT)
|
||||
.then(async (res) => {
|
||||
const body = await res.json();
|
||||
_info("[EMU] Emulator is accessible");
|
||||
})
|
||||
.catch((e) => {
|
||||
_warn("[EMU] Emulator is not accessible");
|
||||
_warn(`[EMU] ${inspect(e)}`);
|
||||
});
|
||||
};
|
||||
|
||||
testEndpoint();
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use((e, req, res, next) => {
|
||||
_err(`[APP] ${inspect(e)}`);
|
||||
res.status(500).json({ error: _err.message });
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
req.startTime = new Date();
|
||||
res.append("Access-Control-Allow-Origin", "*");
|
||||
res.append("Access-Control-Allow-Credentials", "true");
|
||||
res.append("Access-Control-Max-Age", "3600");
|
||||
res.append("Access-Control-Allow-Headers", "*");
|
||||
res.append("Access-Control-Allow-Methods", "*");
|
||||
res.once("finish", () => {
|
||||
const ms = new Date() - req.startTime;
|
||||
(res.statusCode < 400 ? _debug : _err)(
|
||||
`[APP] ${req.method} ${req.url} ${res.statusCode} - ${ms}ms`,
|
||||
statusToColor(res.statusCode),
|
||||
);
|
||||
});
|
||||
next();
|
||||
});
|
||||
|
||||
app.get("/_ready", (_, res) => {
|
||||
res.status(200).send("Compilation complete.");
|
||||
});
|
||||
|
||||
const appConf = {
|
||||
PROXY_PATH: "/proxy",
|
||||
EMULATOR_ENDPOINT: conf.EMULATOR_ENDPOINT,
|
||||
platform: "VNextEmulator",
|
||||
};
|
||||
app.get("/config.json", (_, res) => {
|
||||
res.status(200).json(appConf).end();
|
||||
});
|
||||
|
||||
const proxyProxy = createProxyMiddleware({
|
||||
target: "https://cdb-ms-mpac-pbe.cosmos.azure.com",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
logLevel: conf.LOG_LEVEL,
|
||||
pathRewrite: { "^/proxy": "" },
|
||||
router: (req) => {
|
||||
if (conf.ENDPOINT_DISCOVERY_ENABLED) {
|
||||
let newTarget = req.headers["x-ms-proxy-target"];
|
||||
return newTarget;
|
||||
} else {
|
||||
return conf.EMULATOR_ENDPOINT;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
app.use("/proxy", proxyProxy);
|
||||
|
||||
const unsupported = (req, res) => {
|
||||
res.status(404).send("Unexpected operation. Please create issue.");
|
||||
};
|
||||
|
||||
// TODO: andersonc - I don't believe these are needed for emulator, should confirm and remove.
|
||||
app.use("/api", unsupported);
|
||||
app.use("/_explorer", unsupported);
|
||||
app.use("/explorerProxy", unsupported);
|
||||
app.use(`/${conf.AZURE_TENANT_ID}`, unsupported);
|
||||
|
||||
app.use(express.static("dist"));
|
||||
|
||||
_info(`[EMU] Expecting emulator on [${conf.EMULATOR_ENDPOINT}]`);
|
||||
_info(`[APP] Listening on [${conf.PORT}]`);
|
||||
if (conf.GATEWAY_TLS_ENABLED) {
|
||||
if (!conf.CERT_PATH || !conf.CERT_SECRET) {
|
||||
_err("[APP] Certificate path or secret not provided");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const options = {
|
||||
pfx: fs.readFileSync(conf.CERT_PATH),
|
||||
passphrase: conf.CERT_SECRET,
|
||||
};
|
||||
|
||||
const server = https.createServer(options, app);
|
||||
server.listen(conf.PORT);
|
||||
} else {
|
||||
app.listen(conf.PORT);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
require('./index.js');
|
||||
984
utils/local-proxy/package-lock.json
generated
984
utils/local-proxy/package-lock.json
generated
@@ -1,984 +0,0 @@
|
||||
{
|
||||
"name": "local-proxy",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "local-proxy",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.21.1",
|
||||
"http-proxy-middleware": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-proxy": {
|
||||
"version": "1.17.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz",
|
||||
"integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz",
|
||||
"integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.20.3",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
||||
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.5",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.13.0",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8",
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/content-type": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
||||
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8",
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.3",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.7.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.3.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"merge-descriptors": "1.0.3",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.13.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.19.0",
|
||||
"serve-static": "1.16.2",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
|
||||
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "2.0.1",
|
||||
"unpipe": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-proto": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^4.0.0",
|
||||
"follow-redirects": "^1.0.0",
|
||||
"requires-port": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz",
|
||||
"integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/http-proxy": "^1.17.15",
|
||||
"debug": "^4.3.6",
|
||||
"http-proxy": "^1.18.1",
|
||||
"is-glob": "^4.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
|
||||
"integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ee-first": "1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"forwarded": "0.2.0",
|
||||
"ipaddr.js": "1.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
|
||||
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.16.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
||||
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
||||
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"object-inspect": "^1.13.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "local-proxy",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node main.js",
|
||||
"pack": "cd ../.. && npm run build:proxy && cd utils/local-proxy"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"express": "^4.21.1",
|
||||
"http-proxy-middleware": "^3.0.3"
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
# local-proxy
|
||||
|
||||
Lightweight host for Cosmos Explorer
|
||||
|
||||
## Quickstart
|
||||
|
||||
1. Pre-req - install packages for root project (`cd ../.. && npm ci && cd utils/local-proxy`)
|
||||
2. Install - install packages for local-proxy (`npm ci`)
|
||||
3. Pack - `npm run pack` - builds and packs Cosmos Explorer and copies files into project
|
||||
4. Start - `npm start` - starts the proxy
|
||||
|
||||
```bash
|
||||
cd ../..
|
||||
npm ci
|
||||
cd utils/local-proxy
|
||||
npm ci
|
||||
npm run pack
|
||||
npm start
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
All config is current set via environment variables
|
||||
|
||||
| Name | Options (Default) | Description |
|
||||
| ---------------------------- | ----------------------------------------- | ------------------------------------------------------------ |
|
||||
| `PORT` | number (`1234`) | The port on which the proxy runs. |
|
||||
| `LOG_LEVEL` | `debug`, `info`, `warn`, `error` (`info`) | The logging level for the proxy. |
|
||||
| `EMULATOR_ENDPOINT` | string (`http://localhost:8081`) | The endpoint for the emulator which will be proxied. |
|
||||
| `ENDPOINT_DISCOVERY_ENABLED` | boolean (`false`) | Determine whether the proxy will rewrite the endpoint or not |
|
||||
|
||||
## Dependenies
|
||||
|
||||
Node.js v20+
|
||||
npm (optional)
|
||||
|
||||
## Deployment
|
||||
|
||||
Copy the entire local-proxy directory to wherever you'd like. If you have npm, you can use `npm start`, else `node main.js`
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pushd $(dirname $0) > /dev/null
|
||||
|
||||
echo Creating self-signed certificate
|
||||
|
||||
# Create a self-signed certificate
|
||||
|
||||
export CERT_SECRET=$(openssl rand -base64 20)
|
||||
openssl genrsa 2048 > host.key
|
||||
chmod 400 host.key
|
||||
#openssl req -new -x509 -nodes -sha256 -days 365 -key host.key -out host.cert --passin env:CERT_SECRET -subj "/C=US/ST=WA/L=BELLEVUE/O=Microsoft/OU=Azure Cosmos DB/CN=CHRIS ANDERSON/emailAddress=andersonc@microsoft.com"
|
||||
openssl pkcs12 -export -out host.pfx -inkey host.key -in host.cert --passout env:CERT_SECRET --name "CHRIS ANDERSON"
|
||||
|
||||
export CERT_PATH=$(realpath host.pfx)
|
||||
|
||||
echo CERT_PATH=$CERT_PATH
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
export GATEWAY_TLS_ENABLED=true
|
||||
export EXPLORER_PORT=12345
|
||||
|
||||
# Use node to start so we can kill it later
|
||||
node main.js > ./https-test.log &
|
||||
node_pid=$!
|
||||
echo node pid=$node_pid
|
||||
|
||||
sleep .5
|
||||
|
||||
output=$(curl --insecure -s "https://localhost:12345/_ready")
|
||||
|
||||
kill -KILL $node_pid
|
||||
|
||||
if [ "$output" != "Compilation complete." ]; then
|
||||
echo "Failed to start HTTPS server"
|
||||
cat ./https-test.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo https test completed
|
||||
@@ -24,8 +24,6 @@ const AZURE_TENANT_ID = "72f988bf-86f1-41af-91ab-2d7cd011db47";
|
||||
const RESOURCE_GROUP = "de-e2e-tests";
|
||||
const AZURE_CLIENT_SECRET = process.env.AZURE_CLIENT_SECRET || process.env.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET; // TODO Remove. Exists for backwards compat with old .env files. Prefer AZURE_CLIENT_SECRET
|
||||
|
||||
const ishttps = process.env.GATEWAY_TLS_ENABLED !== "false"; // false -> false, true -> true, default -> true
|
||||
|
||||
if (!AZURE_CLIENT_SECRET) {
|
||||
console.warn("AZURE_CLIENT_SECRET is not set. testExplorer.html will not work.");
|
||||
}
|
||||
@@ -122,23 +120,6 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
...(mode !== "production" && { testExplorer: "./test/testExplorer/TestExplorer.ts" }),
|
||||
};
|
||||
|
||||
// Derive emulator endpoint components from EMULATOR_ENDPOINT (fallback to localhost defaults)
|
||||
const rawEndpoint = process.env.EMULATOR_ENDPOINT || (ishttps ? "https://localhost:8081/" : "http://localhost:8081/");
|
||||
let endpointProtocol = ishttps ? "https" : "http";
|
||||
let endpointHost = "localhost";
|
||||
let endpointPort = "8081";
|
||||
try {
|
||||
const u = new URL(rawEndpoint);
|
||||
endpointProtocol = u.protocol.replace(":", "");
|
||||
endpointHost = u.hostname;
|
||||
endpointPort = u.port || (endpointProtocol === "https" ? "443" : "80");
|
||||
} catch (e) {
|
||||
// Ignore parse errors and keep defaults
|
||||
}
|
||||
const endpointUri = `${endpointProtocol}://${endpointHost}:${endpointPort}`;
|
||||
const primaryKeyConst = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
|
||||
const primaryConnString = `AccountEndpoint=${endpointUri}/;AccountKey=${primaryKeyConst}`;
|
||||
|
||||
const htmlWebpackPlugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "explorer.html",
|
||||
@@ -150,16 +131,10 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
template: "src/Terminal/index.html",
|
||||
chunks: ["terminal"],
|
||||
}),
|
||||
//todo - dynamically include apis
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "quickstart.html",
|
||||
template: "src/quickstart-sql.template.ejs",
|
||||
template: "src/quickstart.html",
|
||||
chunks: ["quickstart"],
|
||||
templateParameters: {
|
||||
endpointUri,
|
||||
primaryKey: primaryKeyConst,
|
||||
primaryConnString,
|
||||
},
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
@@ -236,20 +211,11 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
{ from: "DataExplorer.proj" },
|
||||
{ from: "web.config" },
|
||||
{ from: "quickstart/*.zip" },
|
||||
{ from: "images", to: "images" },
|
||||
],
|
||||
}),
|
||||
new EnvironmentPlugin(envVars),
|
||||
];
|
||||
|
||||
if (process.env.EXPLORER_CONFIG_PATH) {
|
||||
plugins.push(
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [{ from: process.env.EXPLORER_CONFIG_PATH, to: "config.json" }],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (argv.analyze) {
|
||||
plugins.push(new BundleAnalyzerPlugin());
|
||||
}
|
||||
@@ -314,7 +280,7 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
// disableHostCheck: true,
|
||||
liveReload: !isCI,
|
||||
server: {
|
||||
type: ishttps ? "https" : "http",
|
||||
type: "https",
|
||||
},
|
||||
host: "0.0.0.0",
|
||||
port: envVars.PORT,
|
||||
|
||||
Reference in New Issue
Block a user