mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-25 11:51:07 +00:00
Compare commits
1 Commits
jbunster/t
...
iframe-htm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9aeb349d74 |
@@ -1,11 +1,11 @@
|
|||||||
**/node_modules/
|
**/node_modules/
|
||||||
src/**/__mocks__/**/*
|
|
||||||
dist/
|
dist/
|
||||||
Contracts/
|
Contracts/
|
||||||
src/Api/Apis.ts
|
src/Api/Apis.ts
|
||||||
src/AuthType.ts
|
src/AuthType.ts
|
||||||
src/Bindings/BindingHandlersRegisterer.ts
|
src/Bindings/BindingHandlersRegisterer.ts
|
||||||
src/Bindings/ReactBindingHandler.ts
|
src/Bindings/ReactBindingHandler.ts
|
||||||
|
src/Common/ArrayHashMap.ts
|
||||||
src/Common/Constants.ts
|
src/Common/Constants.ts
|
||||||
src/Common/CosmosClient.test.ts
|
src/Common/CosmosClient.test.ts
|
||||||
src/Common/CosmosClient.ts
|
src/Common/CosmosClient.ts
|
||||||
@@ -13,12 +13,15 @@ src/Common/DataAccessUtilityBase.test.ts
|
|||||||
src/Common/DataAccessUtilityBase.ts
|
src/Common/DataAccessUtilityBase.ts
|
||||||
src/Common/EditableUtility.ts
|
src/Common/EditableUtility.ts
|
||||||
src/Common/HashMap.test.ts
|
src/Common/HashMap.test.ts
|
||||||
|
src/Common/HashMap.ts
|
||||||
src/Common/Logger.test.ts
|
src/Common/Logger.test.ts
|
||||||
src/Common/MessageHandler.test.ts
|
src/Common/MessageHandler.test.ts
|
||||||
src/Common/MessageHandler.ts
|
src/Common/MessageHandler.ts
|
||||||
src/Common/MongoProxyClient.test.ts
|
src/Common/MongoProxyClient.test.ts
|
||||||
src/Common/MongoUtility.ts
|
src/Common/MongoUtility.ts
|
||||||
src/Common/NotificationsClientBase.ts
|
src/Common/NotificationsClientBase.ts
|
||||||
|
src/Common/ObjectCache.test.ts
|
||||||
|
src/Common/ObjectCache.ts
|
||||||
src/Common/QueriesClient.ts
|
src/Common/QueriesClient.ts
|
||||||
src/Common/Splitter.ts
|
src/Common/Splitter.ts
|
||||||
src/Config.ts
|
src/Config.ts
|
||||||
@@ -42,6 +45,7 @@ src/Definitions/jquery.d.ts
|
|||||||
src/Definitions/plotly.js-cartesian-dist.d-min.ts
|
src/Definitions/plotly.js-cartesian-dist.d-min.ts
|
||||||
src/Definitions/png.d.ts
|
src/Definitions/png.d.ts
|
||||||
src/Definitions/svg.d.ts
|
src/Definitions/svg.d.ts
|
||||||
|
src/Definitions/worker.d.ts
|
||||||
src/Explorer/ComponentRegisterer.test.ts
|
src/Explorer/ComponentRegisterer.test.ts
|
||||||
src/Explorer/ComponentRegisterer.ts
|
src/Explorer/ComponentRegisterer.ts
|
||||||
src/Explorer/ContextMenuButtonFactory.ts
|
src/Explorer/ContextMenuButtonFactory.ts
|
||||||
@@ -87,7 +91,8 @@ src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts
|
|||||||
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
|
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
|
||||||
src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts
|
src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts
|
||||||
src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts
|
src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts
|
||||||
|
src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts
|
||||||
|
src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts
|
||||||
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts
|
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts
|
||||||
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts
|
src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts
|
||||||
src/Explorer/Menus/ContextMenu.ts
|
src/Explorer/Menus/ContextMenu.ts
|
||||||
@@ -116,13 +121,25 @@ src/Explorer/Panes/AddDatabasePane.ts
|
|||||||
src/Explorer/Panes/BrowseQueriesPane.ts
|
src/Explorer/Panes/BrowseQueriesPane.ts
|
||||||
src/Explorer/Panes/CassandraAddCollectionPane.ts
|
src/Explorer/Panes/CassandraAddCollectionPane.ts
|
||||||
src/Explorer/Panes/ContextualPaneBase.ts
|
src/Explorer/Panes/ContextualPaneBase.ts
|
||||||
|
src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts
|
||||||
|
src/Explorer/Panes/DeleteCollectionConfirmationPane.ts
|
||||||
src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts
|
src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts
|
||||||
src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts
|
src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts
|
||||||
src/Explorer/Panes/GraphStylingPane.ts
|
src/Explorer/Panes/GraphStylingPane.ts
|
||||||
|
src/Explorer/Panes/LoadQueryPane.ts
|
||||||
|
src/Explorer/Panes/NewVertexPane.ts
|
||||||
src/Explorer/Panes/PaneComponents.ts
|
src/Explorer/Panes/PaneComponents.ts
|
||||||
src/Explorer/Panes/RenewAdHocAccessPane.ts
|
src/Explorer/Panes/RenewAdHocAccessPane.ts
|
||||||
|
src/Explorer/Panes/SaveQueryPane.ts
|
||||||
src/Explorer/Panes/SetupNotebooksPane.ts
|
src/Explorer/Panes/SetupNotebooksPane.ts
|
||||||
|
src/Explorer/Panes/StringInputPane.ts
|
||||||
src/Explorer/Panes/SwitchDirectoryPane.ts
|
src/Explorer/Panes/SwitchDirectoryPane.ts
|
||||||
|
src/Explorer/Panes/Tables/AddTableEntityPane.ts
|
||||||
|
src/Explorer/Panes/Tables/EditTableEntityPane.ts
|
||||||
|
src/Explorer/Panes/Tables/EntityPropertyViewModel.ts
|
||||||
|
src/Explorer/Panes/Tables/QuerySelectPane.ts
|
||||||
|
src/Explorer/Panes/Tables/TableColumnOptionsPane.ts
|
||||||
|
src/Explorer/Panes/Tables/TableEntityPane.ts
|
||||||
src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts
|
src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts
|
||||||
src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts
|
src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts
|
||||||
src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts
|
src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts
|
||||||
@@ -237,6 +254,7 @@ src/Utils/QueryUtils.test.ts
|
|||||||
src/applyExplorerBindings.ts
|
src/applyExplorerBindings.ts
|
||||||
src/global.d.ts
|
src/global.d.ts
|
||||||
src/setupTests.ts
|
src/setupTests.ts
|
||||||
|
src/workers/upload/index.ts
|
||||||
src/Explorer/Controls/AccessibleElement/AccessibleElement.tsx
|
src/Explorer/Controls/AccessibleElement/AccessibleElement.tsx
|
||||||
src/Explorer/Controls/Accordion/AccordionComponent.tsx
|
src/Explorer/Controls/Accordion/AccordionComponent.tsx
|
||||||
src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.test.tsx
|
src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.test.tsx
|
||||||
@@ -284,6 +302,8 @@ src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.t
|
|||||||
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx
|
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx
|
||||||
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
|
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
|
||||||
src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.test.tsx
|
src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.test.tsx
|
||||||
|
src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.tsx
|
||||||
|
src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx
|
||||||
src/Explorer/Notebook/NotebookComponent/NotebookComponent.tsx
|
src/Explorer/Notebook/NotebookComponent/NotebookComponent.tsx
|
||||||
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
|
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
|
||||||
src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
|
src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module.exports = {
|
|||||||
browser: true,
|
browser: true,
|
||||||
es6: true,
|
es6: true,
|
||||||
},
|
},
|
||||||
plugins: ["@typescript-eslint", "no-null", "prefer-arrow", "react-hooks"],
|
plugins: ["@typescript-eslint", "no-null", "prefer-arrow"],
|
||||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
globals: {
|
globals: {
|
||||||
Atomics: "readonly",
|
Atomics: "readonly",
|
||||||
@@ -11,7 +11,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: ["./tsconfig.json", "./tsconfig.test.json"],
|
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
jsx: true,
|
jsx: true,
|
||||||
},
|
},
|
||||||
@@ -21,7 +20,7 @@ module.exports = {
|
|||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ["**/*.tsx"],
|
files: ["**/*.tsx"],
|
||||||
extends: ["plugin:react/recommended"],
|
extends: ["plugin:react/recommended"], // TODO: Add react-hooks
|
||||||
plugins: ["react"],
|
plugins: ["react"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -36,7 +35,6 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"no-console": ["error", { allow: ["error", "warn", "dir"] }],
|
"no-console": ["error", { allow: ["error", "warn", "dir"] }],
|
||||||
curly: "error",
|
curly: "error",
|
||||||
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
|
||||||
"@typescript-eslint/no-unused-vars": "error",
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
"@typescript-eslint/no-extraneous-class": "error",
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
"no-null/no-null": "error",
|
"no-null/no-null": "error",
|
||||||
@@ -44,8 +42,6 @@ module.exports = {
|
|||||||
"prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }],
|
"prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }],
|
||||||
eqeqeq: "error",
|
eqeqeq: "error",
|
||||||
"react/display-name": "off",
|
"react/display-name": "off",
|
||||||
"react-hooks/rules-of-hooks": "warn", // TODO: error
|
|
||||||
"react-hooks/exhaustive-deps": "warn", // TODO: error
|
|
||||||
"no-restricted-syntax": [
|
"no-restricted-syntax": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
|||||||
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1 +0,0 @@
|
|||||||
[Preview this branch](https://cosmos-explorer-preview.azurewebsites.net/pull/EDIT_THIS_NUMBER_IN_THE_PR_DESCRIPTION?feature.someFeatureFlagYouMightNeed=true)
|
|
||||||
81
.github/workflows/ci.yml
vendored
81
.github/workflows/ci.yml
vendored
@@ -70,6 +70,7 @@ jobs:
|
|||||||
- run: npm run test
|
- run: npm run test
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
name: "Build"
|
name: "Build"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -91,18 +92,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
path: dist/
|
path: dist/
|
||||||
- name: Upload build to preview blob storage
|
|
||||||
run: az storage blob upload-batch -d '$web' -s 'dist' --account-name cosmosexplorerpreview --subscription cosmosdb-portalteam-generaldemo --destination-path "${{github.event.pull_request.head.sha}}" --account-key="${PREVIEW_STORAGE_KEY}"
|
|
||||||
env:
|
|
||||||
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
|
|
||||||
- name: Upload preview config to blob storage
|
|
||||||
run: az storage blob upload -c '$web' -f ./preview/config.json --account-name cosmosexplorerpreview --subscription cosmosdb-portalteam-generaldemo --name "${{github.event.pull_request.head.sha}}/config.json" --account-key="${PREVIEW_STORAGE_KEY}"
|
|
||||||
env:
|
|
||||||
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
|
|
||||||
endtoendemulator:
|
endtoendemulator:
|
||||||
name: "End To End Emulator Tests"
|
name: "End To End Emulator Tests"
|
||||||
# Temporarily disabled. This test needs to be rewritten in playwright
|
if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/')
|
||||||
if: false
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -127,22 +119,58 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: screenshots
|
name: screenshots
|
||||||
path: failed-*
|
path: failed-*
|
||||||
endtoend:
|
accessibility:
|
||||||
name: "E2E"
|
name: "Accessibility | Hosted"
|
||||||
|
needs: [lint, format, compile, unittest]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js 14.x
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 14.x
|
||||||
|
- name: Accessibility Check
|
||||||
|
run: |
|
||||||
|
# Ubuntu gets mad when webpack runs too many files watchers
|
||||||
|
cat /proc/sys/fs/inotify/max_user_watches
|
||||||
|
sudo sysctl fs.inotify.max_user_watches=524288
|
||||||
|
sudo sysctl -p
|
||||||
|
npm ci
|
||||||
|
npm start &
|
||||||
|
npx wait-on -i 5000 https-get://0.0.0.0:1234/
|
||||||
|
node utils/accesibilityCheck.js
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
NODE_TLS_REJECT_UNAUTHORIZED: 0
|
||||||
|
endtoendhosted:
|
||||||
|
name: "End to End Tests"
|
||||||
|
needs: [cleanupaccounts]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
NODE_TLS_REJECT_UNAUTHORIZED: 0
|
NODE_TLS_REJECT_UNAUTHORIZED: 0
|
||||||
|
PORTAL_RUNNER_SUBSCRIPTION: ${{ secrets.PORTAL_RUNNER_SUBSCRIPTION }}
|
||||||
|
PORTAL_RUNNER_RESOURCE_GROUP: ${{ secrets.PORTAL_RUNNER_RESOURCE_GROUP }}
|
||||||
|
PORTAL_RUNNER_DATABASE_ACCOUNT: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT }}
|
||||||
|
PORTAL_RUNNER_DATABASE_ACCOUNT_KEY: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT_KEY }}
|
||||||
|
PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT: ${{ secrets.PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT }}
|
||||||
|
PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT_KEY: ${{ secrets.PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT_KEY }}
|
||||||
|
NOTEBOOKS_TEST_RUNNER_TENANT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_TENANT_ID }}
|
||||||
|
NOTEBOOKS_TEST_RUNNER_CLIENT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_ID }}
|
||||||
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
|
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
|
||||||
|
PORTAL_RUNNER_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_SQL }}
|
||||||
|
MONGO_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_MONGO }}
|
||||||
|
CASSANDRA_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_CASSANDRA }}
|
||||||
|
TABLES_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_TABLE }}
|
||||||
|
DATA_EXPLORER_ENDPOINT: "https://localhost:1234/hostedExplorer.html"
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
test-file:
|
test-file:
|
||||||
- ./test/cassandra/container.spec.ts
|
- ./test/cassandra/container.spec.ts
|
||||||
- ./test/graph/container.spec.ts
|
- ./test/mongo/mongoIndexPolicy.spec.ts
|
||||||
- ./test/sql/container.spec.ts
|
- ./test/notebooks/uploadAndOpenNotebook.spec.ts
|
||||||
- ./test/mongo/container.spec.ts
|
|
||||||
- ./test/selfServe/selfServeExample.spec.ts
|
- ./test/selfServe/selfServeExample.spec.ts
|
||||||
- ./test/notebooks/upload.spec.ts
|
- ./test/sql/container.spec.ts
|
||||||
- ./test/sql/resourceToken.spec.ts
|
- ./test/sql/resourceToken.spec.ts
|
||||||
- ./test/tables/container.spec.ts
|
- ./test/tables/container.spec.ts
|
||||||
steps:
|
steps:
|
||||||
@@ -153,17 +181,30 @@ jobs:
|
|||||||
node-version: 14.x
|
node-version: 14.x
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm start &
|
- run: npm start &
|
||||||
|
- run: node utils/cleanupDBs.js
|
||||||
- run: npm run wait-for-server
|
- run: npm run wait-for-server
|
||||||
- name: ${{ matrix['test-file'] }}
|
- name: ${{ matrix['test-file'] }}
|
||||||
run: |
|
run: npx jest -c ./jest.config.e2e.js --detectOpenHandles ${{ matrix['test-file'] }}
|
||||||
# Run tests up to three times
|
|
||||||
for i in $(seq 1 3); do npx jest -c ./jest.config.playwright.js ${{ matrix['test-file'] }} && s=0 && break || s=$? && sleep 1; done; (exit $s)
|
|
||||||
shell: bash
|
shell: bash
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: screenshots
|
name: screenshots
|
||||||
path: screenshots/
|
path: failed-*
|
||||||
|
cleanupaccounts:
|
||||||
|
name: "Cleanup Test Database Accounts"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NOTEBOOKS_TEST_RUNNER_CLIENT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_ID }}
|
||||||
|
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js 14.x
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 14.x
|
||||||
|
- run: npm ci
|
||||||
|
- run: node utils/cleanupDBs.js
|
||||||
nuget:
|
nuget:
|
||||||
name: Publish Nuget
|
name: Publish Nuget
|
||||||
if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/')
|
if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/')
|
||||||
|
|||||||
28
.github/workflows/cleanup.yml
vendored
28
.github/workflows/cleanup.yml
vendored
@@ -1,28 +0,0 @@
|
|||||||
# This is a basic workflow to help you get started with Actions
|
|
||||||
|
|
||||||
name: Cleanup End to End Account Resources
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
# Once every hour
|
|
||||||
- cron: "0 * * * *"
|
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
||||||
jobs:
|
|
||||||
# This workflow contains a single job called "build"
|
|
||||||
cleanupaccounts:
|
|
||||||
name: "Cleanup Test Database Accounts"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
NOTEBOOKS_TEST_RUNNER_CLIENT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_ID }}
|
|
||||||
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Use Node.js 14.x
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 14.x
|
|
||||||
- run: npm ci
|
|
||||||
- run: node utils/cleanupDBs.js
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -14,6 +14,4 @@ Contracts/*
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.cache/
|
.cache/
|
||||||
.env
|
.env
|
||||||
failure.png
|
failure.png
|
||||||
screenshots/*
|
|
||||||
GettingStarted-ignore*.ipynb
|
|
||||||
@@ -153,7 +153,7 @@ Cosmos Explorer has been under constant development for over 5 years. As a resul
|
|||||||
|
|
||||||
✅ DO
|
✅ DO
|
||||||
|
|
||||||
- Use [Playwright](https://github.com/microsoft/playwright) and [Jest](https://jestjs.io/)
|
- Use [Puppeteer](https://developers.google.com/web/tools/puppeteer) and [Jest](https://jestjs.io/)
|
||||||
- Write or modify an existing E2E test that covers the primary use case of any major feature.
|
- Write or modify an existing E2E test that covers the primary use case of any major feature.
|
||||||
- Use caution. Do not try to cover every case. End to End tests can be slow and brittle.
|
- Use caution. Do not try to cover every case. End to End tests can be slow and brittle.
|
||||||
|
|
||||||
@@ -188,3 +188,7 @@ Cosmos Explorer has been under constant development for over 5 years. As a resul
|
|||||||
✅ DO
|
✅ DO
|
||||||
|
|
||||||
- Support all [browsers supported by the Azure Portal](https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-supported-browsers-devices)
|
- Support all [browsers supported by the Azure Portal](https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-supported-browsers-devices)
|
||||||
|
- Support IE11
|
||||||
|
- In practice, this should not need to be considered as part of a normal development workflow
|
||||||
|
- Polyfills and transpilation are already provided by our engineering systems.
|
||||||
|
- This requirement will be removed on March 30th, 2021 when Azure drops IE11 support.
|
||||||
|
|||||||
10
externals/iframeResizer.contentWindow.min.js
vendored
10
externals/iframeResizer.contentWindow.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,13 +0,0 @@
|
|||||||
const isCI = require("is-ci");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
exitOnPageError: false,
|
|
||||||
launchOptions: {
|
|
||||||
headless: isCI,
|
|
||||||
slowMo: 10,
|
|
||||||
timeout: 60000,
|
|
||||||
},
|
|
||||||
contextOptions: {
|
|
||||||
ignoreHTTPSErrors: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
12
jest-puppeteer.config.js
Normal file
12
jest-puppeteer.config.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const isCI = require("is-ci");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
launch: {
|
||||||
|
headless: isCI,
|
||||||
|
slowMo: 55,
|
||||||
|
defaultViewport: null,
|
||||||
|
ignoreHTTPSErrors: true,
|
||||||
|
args: ["--disable-web-security"],
|
||||||
|
exitOnPageError: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
5
jest.config.e2e.js
Normal file
5
jest.config.e2e.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: "jest-puppeteer",
|
||||||
|
testMatch: ["<rootDir>/test/**/*.spec.[jt]s?(x)"],
|
||||||
|
setupFiles: ["dotenv/config"],
|
||||||
|
};
|
||||||
@@ -69,8 +69,8 @@ module.exports = {
|
|||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
"^.*[.](svg|png|gif|less|css)$": "<rootDir>/mockModule",
|
"^.*[.](svg|png|gif|less|css)$": "<rootDir>/mockModule",
|
||||||
"@nteract/stateful-components/(.*)$": "<rootDir>/mockModule",
|
"@nteract/stateful-components/(.*)$": "<rootDir>/mockModule",
|
||||||
"@fluentui/react/lib/(.*)$": "@fluentui/react/lib-commonjs/$1", // https://github.com/microsoft/fluentui/wiki/Version-8-release-notes
|
"worker-loader": "<rootDir>/mockModule",
|
||||||
"monaco-editor/(.*)$": "<rootDir>/__mocks__/monaco-editor",
|
"office-ui-fabric-react/lib/(.*)$": "office-ui-fabric-react/lib-commonjs/$1", // https://github.com/OfficeDev/office-ui-fabric-react/wiki/Fabric-6-Release-Notes
|
||||||
"^dnd-core$": "dnd-core/dist/cjs",
|
"^dnd-core$": "dnd-core/dist/cjs",
|
||||||
"^react-dnd$": "react-dnd/dist/cjs",
|
"^react-dnd$": "react-dnd/dist/cjs",
|
||||||
"^react-dnd-html5-backend$": "react-dnd-html5-backend/dist/cjs",
|
"^react-dnd-html5-backend$": "react-dnd-html5-backend/dist/cjs",
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
preset: "jest-playwright-preset",
|
|
||||||
testMatch: ["<rootDir>/test/**/*.spec.[jt]s?(x)"],
|
|
||||||
setupFiles: ["dotenv/config"],
|
|
||||||
testEnvironment: "./test/playwrightEnv.js",
|
|
||||||
setupFilesAfterEnv: ["expect-playwright"],
|
|
||||||
};
|
|
||||||
36467
package-lock.json
generated
36467
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
72
package.json
72
package.json
@@ -5,16 +5,15 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/arm-cosmosdb": "9.1.0",
|
"@azure/arm-cosmosdb": "9.1.0",
|
||||||
"@azure/cosmos": "3.10.5",
|
"@azure/cosmos": "3.9.0",
|
||||||
"@azure/cosmos-language-service": "0.0.5",
|
"@azure/cosmos-language-service": "0.0.5",
|
||||||
"@azure/identity": "1.2.1",
|
"@azure/identity": "1.2.1",
|
||||||
"@azure/ms-rest-nodeauth": "3.0.7",
|
"@azure/ms-rest-nodeauth": "3.0.7",
|
||||||
"@babel/plugin-proposal-class-properties": "7.12.1",
|
"@babel/plugin-proposal-class-properties": "7.12.1",
|
||||||
"@babel/plugin-proposal-decorators": "7.12.12",
|
"@babel/plugin-proposal-decorators": "7.12.12",
|
||||||
"@fluentui/react": "8.10.1",
|
|
||||||
"@jupyterlab/services": "6.0.2",
|
"@jupyterlab/services": "6.0.2",
|
||||||
"@jupyterlab/terminal": "3.0.3",
|
"@jupyterlab/terminal": "3.0.3",
|
||||||
"@microsoft/applicationinsights-web": "2.6.1",
|
"@microsoft/applicationinsights-web": "2.5.9",
|
||||||
"@nteract/commutable": "7.4.2",
|
"@nteract/commutable": "7.4.2",
|
||||||
"@nteract/connected-components": "6.8.2",
|
"@nteract/connected-components": "6.8.2",
|
||||||
"@nteract/core": "15.1.0",
|
"@nteract/core": "15.1.0",
|
||||||
@@ -26,7 +25,7 @@
|
|||||||
"@nteract/iron-icons": "1.0.0",
|
"@nteract/iron-icons": "1.0.0",
|
||||||
"@nteract/jupyter-widgets": "2.0.0",
|
"@nteract/jupyter-widgets": "2.0.0",
|
||||||
"@nteract/logos": "1.0.0",
|
"@nteract/logos": "1.0.0",
|
||||||
"@nteract/markdown": "4.6.0",
|
"@nteract/markdown": "4.4.0",
|
||||||
"@nteract/monaco-editor": "3.2.2",
|
"@nteract/monaco-editor": "3.2.2",
|
||||||
"@nteract/octicons": "2.0.0",
|
"@nteract/octicons": "2.0.0",
|
||||||
"@nteract/outputs": "3.0.9",
|
"@nteract/outputs": "3.0.9",
|
||||||
@@ -44,6 +43,8 @@
|
|||||||
"@types/mkdirp": "1.0.1",
|
"@types/mkdirp": "1.0.1",
|
||||||
"@types/node-fetch": "2.5.7",
|
"@types/node-fetch": "2.5.7",
|
||||||
"@uifabric/react-cards": "0.109.110",
|
"@uifabric/react-cards": "0.109.110",
|
||||||
|
"@uifabric/react-hooks": "7.14.0",
|
||||||
|
"@uifabric/styling": "7.13.7",
|
||||||
"applicationinsights": "1.8.0",
|
"applicationinsights": "1.8.0",
|
||||||
"bootstrap": "3.4.1",
|
"bootstrap": "3.4.1",
|
||||||
"canvas": "file:./canvas",
|
"canvas": "file:./canvas",
|
||||||
@@ -65,7 +66,6 @@
|
|||||||
"i18next": "19.8.4",
|
"i18next": "19.8.4",
|
||||||
"i18next-browser-languagedetector": "6.0.1",
|
"i18next-browser-languagedetector": "6.0.1",
|
||||||
"i18next-http-backend": "1.0.23",
|
"i18next-http-backend": "1.0.23",
|
||||||
"iframe-resizer-react": "1.1.0",
|
|
||||||
"immutable": "4.0.0-rc.12",
|
"immutable": "4.0.0-rc.12",
|
||||||
"is-ci": "2.0.0",
|
"is-ci": "2.0.0",
|
||||||
"jquery": "3.5.1",
|
"jquery": "3.5.1",
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
"monaco-editor": "0.18.1",
|
"monaco-editor": "0.18.1",
|
||||||
"ms": "2.1.3",
|
"ms": "2.1.3",
|
||||||
"msal": "1.4.4",
|
"msal": "1.4.4",
|
||||||
|
"office-ui-fabric-react": "7.164.2",
|
||||||
"p-retry": "4.2.0",
|
"p-retry": "4.2.0",
|
||||||
"plotly.js-cartesian-dist-min": "1.52.3",
|
"plotly.js-cartesian-dist-min": "1.52.3",
|
||||||
"post-robot": "10.0.42",
|
|
||||||
"q": "1.5.1",
|
"q": "1.5.1",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-animate-height": "2.0.8",
|
"react-animate-height": "2.0.8",
|
||||||
@@ -93,7 +93,6 @@
|
|||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rx-jupyter": "5.5.12",
|
"rx-jupyter": "5.5.12",
|
||||||
"rxjs": "6.6.3",
|
"rxjs": "6.6.3",
|
||||||
"sanitize-html": "2.3.3",
|
|
||||||
"styled-components": "4.3.2",
|
"styled-components": "4.3.2",
|
||||||
"swr": "0.4.0",
|
"swr": "0.4.0",
|
||||||
"terser-webpack-plugin": "3.1.0",
|
"terser-webpack-plugin": "3.1.0",
|
||||||
@@ -101,10 +100,10 @@
|
|||||||
"utility-types": "3.10.0"
|
"utility-types": "3.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.14.0",
|
"@babel/core": "7.9.0",
|
||||||
"@babel/preset-env": "7.14.1",
|
"@babel/preset-env": "7.9.0",
|
||||||
"@babel/preset-react": "7.13.13",
|
"@babel/preset-react": "7.9.4",
|
||||||
"@babel/preset-typescript": "7.13.0",
|
"@babel/preset-typescript": "7.9.0",
|
||||||
"@testing-library/react": "11.2.3",
|
"@testing-library/react": "11.2.3",
|
||||||
"@types/applicationinsights-js": "1.0.7",
|
"@types/applicationinsights-js": "1.0.7",
|
||||||
"@types/codemirror": "0.0.56",
|
"@types/codemirror": "0.0.56",
|
||||||
@@ -112,25 +111,28 @@
|
|||||||
"@types/d3": "5.9.2",
|
"@types/d3": "5.9.2",
|
||||||
"@types/enzyme": "3.10.7",
|
"@types/enzyme": "3.10.7",
|
||||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||||
|
"@types/expect-puppeteer": "4.4.5",
|
||||||
"@types/hasher": "0.0.31",
|
"@types/hasher": "0.0.31",
|
||||||
"@types/jest": "26.0.20",
|
"@types/jest": "26.0.20",
|
||||||
|
"@types/jest-environment-puppeteer": "4.4.1",
|
||||||
"@types/memoize-one": "4.1.1",
|
"@types/memoize-one": "4.1.1",
|
||||||
"@types/node": "12.11.1",
|
"@types/node": "12.11.1",
|
||||||
"@types/post-robot": "10.0.1",
|
|
||||||
"@types/promise.prototype.finally": "2.0.3",
|
"@types/promise.prototype.finally": "2.0.3",
|
||||||
|
"@types/prop-types": "15.5.8",
|
||||||
|
"@types/puppeteer": "5.4.3",
|
||||||
"@types/q": "1.5.1",
|
"@types/q": "1.5.1",
|
||||||
"@types/react": "17.0.3",
|
"@types/react": "17.0.0",
|
||||||
"@types/react-dom": "17.0.3",
|
"@types/react-dom": "17.0.0",
|
||||||
"@types/react-notification-system": "0.2.39",
|
"@types/react-notification-system": "0.2.39",
|
||||||
"@types/react-redux": "7.1.7",
|
"@types/react-redux": "7.1.7",
|
||||||
"@types/sanitize-html": "1.27.2",
|
|
||||||
"@types/sinon": "2.3.3",
|
"@types/sinon": "2.3.3",
|
||||||
"@types/styled-components": "5.1.1",
|
"@types/styled-components": "5.1.1",
|
||||||
"@types/underscore": "1.7.36",
|
"@types/underscore": "1.7.36",
|
||||||
"@typescript-eslint/eslint-plugin": "4.22.1",
|
"@typescript-eslint/eslint-plugin": "4.0.1",
|
||||||
"@typescript-eslint/parser": "4.22.1",
|
"@typescript-eslint/parser": "4.0.1",
|
||||||
"babel-jest": "26.6.3",
|
"axe-puppeteer": "1.1.0",
|
||||||
"babel-loader": "8.2.2",
|
"babel-jest": "24.9.0",
|
||||||
|
"babel-loader": "8.1.0",
|
||||||
"buffer": "5.1.0",
|
"buffer": "5.1.0",
|
||||||
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
||||||
"create-file-webpack": "1.0.2",
|
"create-file-webpack": "1.0.2",
|
||||||
@@ -138,23 +140,21 @@
|
|||||||
"enzyme": "3.11.0",
|
"enzyme": "3.11.0",
|
||||||
"enzyme-adapter-react-16": "1.15.5",
|
"enzyme-adapter-react-16": "1.15.5",
|
||||||
"enzyme-to-json": "3.6.1",
|
"enzyme-to-json": "3.6.1",
|
||||||
"eslint": "7.25.0",
|
"eslint": "7.8.1",
|
||||||
"eslint-cli": "1.1.1",
|
"eslint-cli": "1.1.1",
|
||||||
"eslint-plugin-no-null": "1.0.2",
|
"eslint-plugin-no-null": "1.0.2",
|
||||||
"eslint-plugin-prefer-arrow": "1.2.2",
|
"eslint-plugin-prefer-arrow": "1.2.2",
|
||||||
"eslint-plugin-react-hooks": "4.2.0",
|
"eslint-plugin-react-hooks": "4.2.0",
|
||||||
"expect-playwright": "0.3.3",
|
|
||||||
"expose-loader": "0.7.5",
|
"expose-loader": "0.7.5",
|
||||||
"fast-glob": "3.2.5",
|
"fast-glob": "3.2.5",
|
||||||
"file-loader": "2.0.0",
|
"file-loader": "2.0.0",
|
||||||
"fs-extra": "7.0.0",
|
"fs-extra": "7.0.0",
|
||||||
"html-inline-css-webpack-plugin": "1.11.0",
|
|
||||||
"html-loader": "0.5.5",
|
"html-loader": "0.5.5",
|
||||||
"html-loader-jest": "0.2.1",
|
"html-loader-jest": "0.2.1",
|
||||||
"html-webpack-plugin": "4.5.2",
|
"html-webpack-plugin": "3.2.0",
|
||||||
"jest": "26.6.3",
|
"jest": "25.5.4",
|
||||||
"jest-canvas-mock": "2.1.0",
|
"jest-canvas-mock": "2.1.0",
|
||||||
"jest-playwright-preset": "1.5.1",
|
"jest-puppeteer": "4.4.0",
|
||||||
"jest-trx-results-processor": "0.0.7",
|
"jest-trx-results-processor": "0.0.7",
|
||||||
"less": "3.8.1",
|
"less": "3.8.1",
|
||||||
"less-loader": "4.1.0",
|
"less-loader": "4.1.0",
|
||||||
@@ -162,23 +162,23 @@
|
|||||||
"mini-css-extract-plugin": "0.4.3",
|
"mini-css-extract-plugin": "0.4.3",
|
||||||
"monaco-editor-webpack-plugin": "1.7.0",
|
"monaco-editor-webpack-plugin": "1.7.0",
|
||||||
"node-fetch": "2.6.1",
|
"node-fetch": "2.6.1",
|
||||||
"playwright": "1.10.0",
|
|
||||||
"prettier": "2.2.1",
|
"prettier": "2.2.1",
|
||||||
|
"puppeteer": "8.0.0",
|
||||||
"raw-loader": "0.5.1",
|
"raw-loader": "0.5.1",
|
||||||
"react-dev-utils": "11.0.4",
|
|
||||||
"rimraf": "3.0.0",
|
"rimraf": "3.0.0",
|
||||||
"sinon": "3.2.1",
|
"sinon": "3.2.1",
|
||||||
"style-loader": "0.23.0",
|
"style-loader": "0.23.0",
|
||||||
"ts-loader": "9.1.2",
|
"ts-loader": "6.2.2",
|
||||||
"tslint": "6.1.3",
|
"tslint": "5.11.0",
|
||||||
"tslint-microsoft-contrib": "6.2.0",
|
"tslint-microsoft-contrib": "6.0.0",
|
||||||
"typescript": "4.3.0-beta",
|
"typescript": "4.0.2",
|
||||||
"url-loader": "1.1.1",
|
"url-loader": "1.1.1",
|
||||||
"wait-on": "4.0.2",
|
"wait-on": "4.0.2",
|
||||||
"webpack": "4.46.0",
|
"webpack": "4.43.0",
|
||||||
"webpack-bundle-analyzer": "3.6.1",
|
"webpack-bundle-analyzer": "3.6.1",
|
||||||
"webpack-cli": "3.3.10",
|
"webpack-cli": "3.3.10",
|
||||||
"webpack-dev-server": "3.11.0"
|
"webpack-dev-server": "3.11.0",
|
||||||
|
"worker-loader": "2.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node --max-old-space-size=10196 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
|
"start": "node --max-old-space-size=10196 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
"pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress",
|
"pack:fast": "node --max_old_space_size=10196 ./node_modules/webpack/bin/webpack.js --mode development --progress",
|
||||||
"copyToConsumers": "node copyToConsumers",
|
"copyToConsumers": "node copyToConsumers",
|
||||||
"test": "rimraf coverage && jest",
|
"test": "rimraf coverage && jest",
|
||||||
"test:e2e": "jest -c ./jest.config.playwright.js --detectOpenHandles",
|
"test:e2e": "jest -c ./jest.config.e2e.js --detectOpenHandles",
|
||||||
"watch": "npm run start",
|
"watch": "npm run start",
|
||||||
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
||||||
"build:ase": "gulp build:ase",
|
"build:ase": "gulp build:ase",
|
||||||
@@ -201,8 +201,8 @@
|
|||||||
"format:check": "prettier --check \"{src,test}/**/*.{ts,tsx,html}\" \"*.{js,html}\"",
|
"format:check": "prettier --check \"{src,test}/**/*.{ts,tsx,html}\" \"*.{js,html}\"",
|
||||||
"lint": "tslint --project tsconfig.json && eslint \"**/*.{ts,tsx}\"",
|
"lint": "tslint --project tsconfig.json && eslint \"**/*.{ts,tsx}\"",
|
||||||
"build:contracts": "npm run compile:contracts",
|
"build:contracts": "npm run compile:contracts",
|
||||||
"strict:find": "node ./strict-null-checks/find.js",
|
"strictEligibleFiles": "node ./strict-migration-tools/index.js",
|
||||||
"strict:add": "node ./strict-null-checks/auto-add.js",
|
"autoAddStrictEligibleFiles": "node ./strict-migration-tools/autoAdd.js",
|
||||||
"compile:fullStrict": "tsc -p ./tsconfig.json --strictNullChecks",
|
"compile:fullStrict": "tsc -p ./tsconfig.json --strictNullChecks",
|
||||||
"generateARMClients": "ts-node --compiler-options '{\"module\":\"commonjs\"}' utils/armClientGenerator/generator.ts"
|
"generateARMClients": "ts-node --compiler-options '{\"module\":\"commonjs\"}' utils/armClientGenerator/generator.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
[defaults]
|
|
||||||
group = stfaul
|
|
||||||
sku = P1v2
|
|
||||||
appserviceplan = stfaul_asp_Linux_centralus_0
|
|
||||||
location = centralus
|
|
||||||
web = cosmos-explorer-preview
|
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Cosmos Explorer Preview
|
|
||||||
|
|
||||||
Cosmos Explorer Preview makes it possible to try a working version of any commit on master or in a PR. No need to run the app locally or deploy to staging.
|
|
||||||
|
|
||||||
Initial support is for Hosted (Connection string only) or the Azure Portal. Examples:
|
|
||||||
|
|
||||||
Connection string URLs: https://cosmos-explorer-preview.azurewebsites.net/commit/COMMIT_SHA/hostedExplorer.html
|
|
||||||
Portal URLs: https://ms.portal.azure.com/?dataExplorerSource=https://cosmos-explorer-preview.azurewebsites.net/commit/COMMIT_SHA/explorer.html#home
|
|
||||||
|
|
||||||
In both cases replace `COMMIT_SHA` with the commit you want to view. It must have already completed its build on GitHub Actions.
|
|
||||||
|
|
||||||
### Architechture
|
|
||||||
|
|
||||||
- This folder contains a NodeJS app deployed to Azure App Service that powers preview URLs:
|
|
||||||
- Paths starting with `/commit/` are proxied to an Azure Storage account containing build artifacts
|
|
||||||
- Paths starting with `/proxy/` are proxied dynamically to Cosmos account endpoints. Required otherwise CORS would need to be configured for every account accessed.
|
|
||||||
- Paths starting with `/api/` are proxied to Portal APIs that do not support CORS.
|
|
||||||
- On GitHub Actions build completion:
|
|
||||||
- All files in dist are uploaded to an Azure Storage account namespaced by the SHA of the commit
|
|
||||||
- `/preview/config.json` is uploaded to the same folder with preview specific configuration
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"PROXY_PATH": "/proxy"
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const { createProxyMiddleware } = require("http-proxy-middleware");
|
|
||||||
const port = process.env.PORT || 3000;
|
|
||||||
const fetch = require("node-fetch");
|
|
||||||
|
|
||||||
const api = createProxyMiddleware("/api", {
|
|
||||||
target: "https://main.documentdb.ext.azure.com",
|
|
||||||
changeOrigin: true,
|
|
||||||
logLevel: "debug",
|
|
||||||
bypass: (req, res) => {
|
|
||||||
if (req.method === "OPTIONS") {
|
|
||||||
res.statusCode = 200;
|
|
||||||
res.send();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const proxy = createProxyMiddleware("/proxy", {
|
|
||||||
target: "https://main.documentdb.ext.azure.com",
|
|
||||||
changeOrigin: true,
|
|
||||||
secure: false,
|
|
||||||
logLevel: "debug",
|
|
||||||
pathRewrite: { "^/proxy": "" },
|
|
||||||
router: (req) => {
|
|
||||||
let newTarget = req.headers["x-ms-proxy-target"];
|
|
||||||
return newTarget;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const commit = createProxyMiddleware("/commit", {
|
|
||||||
target: "https://cosmosexplorerpreview.blob.core.windows.net",
|
|
||||||
changeOrigin: true,
|
|
||||||
secure: false,
|
|
||||||
logLevel: "debug",
|
|
||||||
pathRewrite: { "^/commit": "$web/" },
|
|
||||||
});
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.use(api);
|
|
||||||
app.use(proxy);
|
|
||||||
app.use(commit);
|
|
||||||
app.get("/pull/:pr(\\d+)", (req, res) => {
|
|
||||||
const pr = req.params.pr;
|
|
||||||
const [, query] = req.originalUrl.split("?");
|
|
||||||
const search = new URLSearchParams(query);
|
|
||||||
|
|
||||||
fetch("https://api.github.com/repos/Azure/cosmos-explorer/pulls/" + pr)
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then(({ head: { ref, sha } }) => {
|
|
||||||
const prUrl = new URL("https://github.com/Azure/cosmos-explorer/pull/" + pr);
|
|
||||||
prUrl.hash = ref;
|
|
||||||
search.set("feature.pr", prUrl.href);
|
|
||||||
|
|
||||||
const explorer = new URL("https://cosmos-explorer-preview.azurewebsites.net/commit/" + sha + "/explorer.html");
|
|
||||||
explorer.search = search.toString();
|
|
||||||
|
|
||||||
const portal = new URL("https://ms.portal.azure.com/");
|
|
||||||
portal.searchParams.set("dataExplorerSource", explorer.href);
|
|
||||||
|
|
||||||
return res.redirect(portal.href);
|
|
||||||
})
|
|
||||||
.catch(() => res.sendStatus(500));
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(port, () => {
|
|
||||||
console.log(`Example app listening on port: ${port}`);
|
|
||||||
});
|
|
||||||
1146
preview/package-lock.json
generated
1146
preview/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cosmos-explorer-preview",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"deploy": "az webapp up -n cosmos-explorer-preview --subscription cosmosdb-portalteam-generaldemo -g stfaul",
|
|
||||||
"start": "node index.js",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Microsoft Corporation",
|
|
||||||
"dependencies": {
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"http-proxy-middleware": "^1.1.0",
|
|
||||||
"node-fetch": "^2.6.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,13 @@ export interface ReactAdapter {
|
|||||||
export class Registerer {
|
export class Registerer {
|
||||||
public static register(): void {
|
public static register(): void {
|
||||||
ko.bindingHandlers.react = {
|
ko.bindingHandlers.react = {
|
||||||
init: (element: any, wrappedValueAccessor: () => any) => {
|
init: (
|
||||||
|
element: any,
|
||||||
|
wrappedValueAccessor: () => any,
|
||||||
|
allBindings?: ko.AllBindings,
|
||||||
|
viewModel?: any,
|
||||||
|
bindingContext?: ko.BindingContext
|
||||||
|
) => {
|
||||||
const adapter: ReactAdapter = wrappedValueAccessor();
|
const adapter: ReactAdapter = wrappedValueAccessor();
|
||||||
|
|
||||||
if (adapter.setElement) {
|
if (adapter.setElement) {
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
.schema-analyzer-cell-outputs {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.schema-analyzer-cell-output {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 2px;
|
|
||||||
box-shadow: rgba(0, 0, 0, 13%) 0px 1.6px 3.6px 0px, rgba(0, 0, 0, 11%) 0px 0.3px 0.9px 0px;
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import { createImmutableOutput, JSONObject, OnDiskOutput } from "@nteract/commutable";
|
|
||||||
// import outputs individually to avoid increasing the bundle size
|
|
||||||
import { KernelOutputError } from "@nteract/outputs/lib/components/kernel-output-error";
|
|
||||||
import { Output } from "@nteract/outputs/lib/components/output";
|
|
||||||
import { StreamText } from "@nteract/outputs/lib/components/stream-text";
|
|
||||||
import { ContentRef } from "@nteract/types";
|
|
||||||
import "bootstrap/dist/css/bootstrap.css";
|
|
||||||
import postRobot from "post-robot";
|
|
||||||
import * as React from "react";
|
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import "../../externals/iframeResizer.contentWindow.min.js"; // Required for iFrameResizer to work
|
|
||||||
import "../Explorer/Notebook/NotebookRenderer/base.css";
|
|
||||||
import "../Explorer/Notebook/NotebookRenderer/default.css";
|
|
||||||
import "./CellOutputViewer.less";
|
|
||||||
import { TransformMedia } from "./TransformMedia";
|
|
||||||
|
|
||||||
export interface CellOutputViewerProps {
|
|
||||||
id: string;
|
|
||||||
contentRef: ContentRef;
|
|
||||||
outputsContainerClassName: string;
|
|
||||||
outputClassName: string;
|
|
||||||
outputs: OnDiskOutput[];
|
|
||||||
onMetadataChange: (metadata: JSONObject, mediaType: string, index?: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onInit = async () => {
|
|
||||||
postRobot.on(
|
|
||||||
"props",
|
|
||||||
{
|
|
||||||
window: window.parent,
|
|
||||||
domain: window.location.origin,
|
|
||||||
},
|
|
||||||
(event) => {
|
|
||||||
// Typescript definition for event is wrong. So read props by casting to <any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const props = (event as any).data as CellOutputViewerProps;
|
|
||||||
const outputs = (
|
|
||||||
<div data-iframe-height className={props.outputsContainerClassName}>
|
|
||||||
{props.outputs?.map((output, index) => (
|
|
||||||
<div className={props.outputClassName} key={index}>
|
|
||||||
<Output output={createImmutableOutput(output)} key={index}>
|
|
||||||
<TransformMedia
|
|
||||||
output_type={"display_data"}
|
|
||||||
id={props.id}
|
|
||||||
contentRef={props.contentRef}
|
|
||||||
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
|
||||||
/>
|
|
||||||
<TransformMedia
|
|
||||||
output_type={"execute_result"}
|
|
||||||
id={props.id}
|
|
||||||
contentRef={props.contentRef}
|
|
||||||
onMetadataChange={(metadata, mediaType) => props.onMetadataChange(metadata, mediaType, index)}
|
|
||||||
/>
|
|
||||||
<KernelOutputError />
|
|
||||||
<StreamText />
|
|
||||||
</Output>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
ReactDOM.render(outputs, document.getElementById("cellOutput"));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Entry point
|
|
||||||
window.addEventListener("load", onInit);
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
import { ImmutableDisplayData, ImmutableExecuteResult, JSONObject } from "@nteract/commutable";
|
|
||||||
// import outputs individually to avoid increasing the bundle size
|
|
||||||
import { HTML } from "@nteract/outputs/lib/components/media/html";
|
|
||||||
import { Image } from "@nteract/outputs/lib/components/media/image";
|
|
||||||
import { JavaScript } from "@nteract/outputs/lib/components/media/javascript";
|
|
||||||
import { Json } from "@nteract/outputs/lib/components/media/json";
|
|
||||||
import { LaTeX } from "@nteract/outputs/lib/components/media/latex";
|
|
||||||
import { Plain } from "@nteract/outputs/lib/components/media/plain";
|
|
||||||
import { SVG } from "@nteract/outputs/lib/components/media/svg";
|
|
||||||
import { ContentRef } from "@nteract/types";
|
|
||||||
import React, { Suspense } from "react";
|
|
||||||
|
|
||||||
const EmptyTransform = (): JSX.Element => <></>;
|
|
||||||
|
|
||||||
const displayOrder = [
|
|
||||||
"application/vnd.jupyter.widget-view+json",
|
|
||||||
"application/vnd.vega.v5+json",
|
|
||||||
"application/vnd.vega.v4+json",
|
|
||||||
"application/vnd.vega.v3+json",
|
|
||||||
"application/vnd.vega.v2+json",
|
|
||||||
"application/vnd.vegalite.v4+json",
|
|
||||||
"application/vnd.vegalite.v3+json",
|
|
||||||
"application/vnd.vegalite.v2+json",
|
|
||||||
"application/vnd.vegalite.v1+json",
|
|
||||||
"application/geo+json",
|
|
||||||
"application/vnd.plotly.v1+json",
|
|
||||||
"text/vnd.plotly.v1+html",
|
|
||||||
"application/x-nteract-model-debug+json",
|
|
||||||
"application/vnd.dataresource+json",
|
|
||||||
"application/vdom.v1+json",
|
|
||||||
"application/json",
|
|
||||||
"application/javascript",
|
|
||||||
"text/html",
|
|
||||||
"text/markdown",
|
|
||||||
"text/latex",
|
|
||||||
"image/svg+xml",
|
|
||||||
"image/gif",
|
|
||||||
"image/png",
|
|
||||||
"image/jpeg",
|
|
||||||
"text/plain",
|
|
||||||
];
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const transformsById = new Map<string, React.ComponentType<any>>([
|
|
||||||
["text/vnd.plotly.v1+html", React.lazy(() => import("@nteract/transform-plotly"))],
|
|
||||||
["application/vnd.plotly.v1+json", React.lazy(() => import("@nteract/transform-plotly"))],
|
|
||||||
["application/geo+json", EmptyTransform], // TODO: The geojson transform will likely need some work because of the basemap URL(s)
|
|
||||||
["application/x-nteract-model-debug+json", React.lazy(() => import("@nteract/transform-model-debug"))],
|
|
||||||
["application/vnd.dataresource+json", React.lazy(() => import("@nteract/data-explorer"))],
|
|
||||||
["application/vnd.jupyter.widget-view+json", React.lazy(() => import("./transforms/WidgetDisplay"))],
|
|
||||||
["application/vnd.vegalite.v1+json", React.lazy(() => import("./transforms/VegaLite1"))],
|
|
||||||
["application/vnd.vegalite.v2+json", React.lazy(() => import("./transforms/VegaLite2"))],
|
|
||||||
["application/vnd.vegalite.v3+json", React.lazy(() => import("./transforms/VegaLite3"))],
|
|
||||||
["application/vnd.vegalite.v4+json", React.lazy(() => import("./transforms/VegaLite4"))],
|
|
||||||
["application/vnd.vega.v2+json", React.lazy(() => import("./transforms/Vega2"))],
|
|
||||||
["application/vnd.vega.v3+json", React.lazy(() => import("./transforms/Vega3"))],
|
|
||||||
["application/vnd.vega.v4+json", React.lazy(() => import("./transforms/Vega4"))],
|
|
||||||
["application/vnd.vega.v5+json", React.lazy(() => import("./transforms/Vega5"))],
|
|
||||||
["application/vdom.v1+json", React.lazy(() => import("@nteract/transform-vdom"))],
|
|
||||||
["application/json", Json],
|
|
||||||
["application/javascript", JavaScript],
|
|
||||||
["text/html", HTML],
|
|
||||||
["text/markdown", React.lazy(() => import("@nteract/outputs/lib/components/media/markdown"))], // Markdown increases the bundle size so lazy load it
|
|
||||||
["text/latex", LaTeX],
|
|
||||||
["image/svg+xml", SVG],
|
|
||||||
["image/gif", Image],
|
|
||||||
["image/png", Image],
|
|
||||||
["image/jpeg", Image],
|
|
||||||
["text/plain", Plain],
|
|
||||||
]);
|
|
||||||
|
|
||||||
interface TransformMediaProps {
|
|
||||||
output_type: string;
|
|
||||||
id: string;
|
|
||||||
contentRef: ContentRef;
|
|
||||||
output?: ImmutableDisplayData | ImmutableExecuteResult;
|
|
||||||
onMetadataChange: (metadata: JSONObject, mediaType: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TransformMedia = (props: TransformMediaProps): JSX.Element => {
|
|
||||||
const { Media, mediaType, data, metadata } = getMediaInfo(props);
|
|
||||||
|
|
||||||
// If we had no valid result, return an empty output
|
|
||||||
if (!mediaType || !data) {
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Suspense fallback={<div>Loading...</div>}>
|
|
||||||
<Media
|
|
||||||
onMetadataChange={props.onMetadataChange}
|
|
||||||
data={data}
|
|
||||||
metadata={metadata}
|
|
||||||
contentRef={props.contentRef}
|
|
||||||
id={props.id}
|
|
||||||
/>
|
|
||||||
</Suspense>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getMediaInfo = (props: TransformMediaProps) => {
|
|
||||||
const { output, output_type } = props;
|
|
||||||
// This component should only be used with display data and execute result
|
|
||||||
if (!output || !(output_type === "display_data" || output_type === "execute_result")) {
|
|
||||||
console.warn("connected transform media managed to get a non media bundle output");
|
|
||||||
return {
|
|
||||||
Media: EmptyTransform,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first mediaType in the output data that we support with a handler
|
|
||||||
const mediaType = displayOrder.find(
|
|
||||||
(key) =>
|
|
||||||
Object.prototype.hasOwnProperty.call(output.data, key) &&
|
|
||||||
(Object.prototype.hasOwnProperty.call(transformsById, key) || transformsById.get(key))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mediaType) {
|
|
||||||
const metadata = output.metadata.get(mediaType);
|
|
||||||
const data = output.data[mediaType];
|
|
||||||
|
|
||||||
const Media = transformsById.get(mediaType);
|
|
||||||
return {
|
|
||||||
Media,
|
|
||||||
mediaType,
|
|
||||||
data,
|
|
||||||
metadata,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
Media: EmptyTransform,
|
|
||||||
mediaType,
|
|
||||||
output,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransformMedia;
|
|
||||||
@@ -1,12 +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>Cell Output Viewer</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="cellOutput" id="cellOutput"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Vega2 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Vega3 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Vega4 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { Vega5 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { VegaLite1 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { VegaLite2 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { VegaLite3 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { VegaLite4 as default } from "@nteract/transform-vega";
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { WidgetDisplay as default } from "@nteract/jupyter-widgets";
|
|
||||||
@@ -1,9 +1,49 @@
|
|||||||
|
import { HashMap } from "./HashMap";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash map of arrays which allows to:
|
* Hash map of arrays which allows to:
|
||||||
* - push an item by key: add to array and create array if needed
|
* - push an item by key: add to array and create array if needed
|
||||||
* - remove item by key: remove from array and delete array if needed
|
* - remove item by key: remove from array and delete array if needed
|
||||||
*/
|
*/
|
||||||
export class ArrayHashMap<T> extends Map<string, T[]> {
|
|
||||||
|
export class ArrayHashMap<T> {
|
||||||
|
private store: HashMap<T[]>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.store = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public has(key: string): boolean {
|
||||||
|
return this.store.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: string): T[] {
|
||||||
|
return this.store.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public size(): number {
|
||||||
|
return this.store.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
this.store.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public keys(): string[] {
|
||||||
|
return this.store.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete(key: string): boolean {
|
||||||
|
return this.store.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public forEach(key: string, iteratorFct: (value: T) => void) {
|
||||||
|
const values = this.store.get(key);
|
||||||
|
if (values) {
|
||||||
|
values.forEach((value) => iteratorFct(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert item into array.
|
* Insert item into array.
|
||||||
* If no array, create one.
|
* If no array, create one.
|
||||||
@@ -12,8 +52,16 @@ export class ArrayHashMap<T> extends Map<string, T[]> {
|
|||||||
* @param item
|
* @param item
|
||||||
*/
|
*/
|
||||||
public push(key: string, item: T): void {
|
public push(key: string, item: T): void {
|
||||||
const array = this.get(key);
|
let itemsArray: T[] = this.store.get(key);
|
||||||
array ? array.includes(item) || array.push(item) : this.set(key, [item]);
|
if (!itemsArray) {
|
||||||
|
itemsArray = [item];
|
||||||
|
this.store.set(key, itemsArray);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemsArray.indexOf(item) === -1) {
|
||||||
|
itemsArray.push(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,11 +70,18 @@ export class ArrayHashMap<T> extends Map<string, T[]> {
|
|||||||
* @param key
|
* @param key
|
||||||
* @param itemToRemove
|
* @param itemToRemove
|
||||||
*/
|
*/
|
||||||
public remove(key: string, itemToRemove: T): void {
|
public remove(key: string, itemToRemove: T) {
|
||||||
const array = this.get(key);
|
if (!this.store.has(key)) {
|
||||||
if (array) {
|
return;
|
||||||
const remaining = array.filter((item) => item !== itemToRemove);
|
}
|
||||||
remaining.length ? this.set(key, remaining) : this.delete(key);
|
|
||||||
|
const itemsArray = this.store.get(key);
|
||||||
|
const index = itemsArray.indexOf(itemToRemove);
|
||||||
|
if (index >= 0) {
|
||||||
|
itemsArray.splice(index, 1);
|
||||||
|
if (itemsArray.length === 0) {
|
||||||
|
this.store.delete(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,18 +65,28 @@ export class ClientDefaults {
|
|||||||
public static readonly arcadiaTokenRefreshIntervalPaddingMs: number = 2000;
|
public static readonly arcadiaTokenRefreshIntervalPaddingMs: number = 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AccountKind {
|
export class AccountKind {
|
||||||
DocumentDB = "DocumentDB",
|
public static DocumentDB: string = "DocumentDB";
|
||||||
MongoDB = "MongoDB",
|
public static MongoDB: string = "MongoDB";
|
||||||
Parse = "Parse",
|
public static Parse: string = "Parse";
|
||||||
GlobalDocumentDB = "GlobalDocumentDB",
|
public static GlobalDocumentDB: string = "GlobalDocumentDB";
|
||||||
Default = "DocumentDB",
|
public static Default: string = AccountKind.DocumentDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CorrelationBackend {
|
export class CorrelationBackend {
|
||||||
public static Url: string = "https://aka.ms/cosmosdbanalytics";
|
public static Url: string = "https://aka.ms/cosmosdbanalytics";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DefaultAccountExperience {
|
||||||
|
public static DocumentDB: string = "DocumentDB";
|
||||||
|
public static Graph: string = "Graph";
|
||||||
|
public static MongoDB: string = "MongoDB";
|
||||||
|
public static ApiForMongoDB: string = "Azure Cosmos DB for MongoDB API";
|
||||||
|
public static Table: string = "Table";
|
||||||
|
public static Cassandra: string = "Cassandra";
|
||||||
|
public static Default: string = DefaultAccountExperience.DocumentDB;
|
||||||
|
}
|
||||||
|
|
||||||
export class CapabilityNames {
|
export class CapabilityNames {
|
||||||
public static EnableTable: string = "EnableTable";
|
public static EnableTable: string = "EnableTable";
|
||||||
public static EnableGremlin: string = "EnableGremlin";
|
public static EnableGremlin: string = "EnableGremlin";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ResourceType } from "@azure/cosmos/dist-esm/common/constants";
|
import { ResourceType } from "@azure/cosmos/dist-esm/common/constants";
|
||||||
import { Platform, resetConfigContext, updateConfigContext } from "../ConfigContext";
|
import { configContext, Platform, updateConfigContext, resetConfigContext } from "../ConfigContext";
|
||||||
import { updateUserContext } from "../UserContext";
|
import { updateUserContext } from "../UserContext";
|
||||||
import { endpoint, getTokenFromAuthService, requestPlugin, tokenProvider } from "./CosmosClient";
|
import { endpoint, getTokenFromAuthService, requestPlugin, tokenProvider } from "./CosmosClient";
|
||||||
|
|
||||||
@@ -91,6 +91,7 @@ describe("endpoint", () => {
|
|||||||
location: "foo",
|
location: "foo",
|
||||||
type: "foo",
|
type: "foo",
|
||||||
kind: "foo",
|
kind: "foo",
|
||||||
|
tags: [],
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: "bar",
|
documentEndpoint: "bar",
|
||||||
gremlinEndpoint: "foo",
|
gremlinEndpoint: "foo",
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const tokenProvider = async (requestInfo: RequestInfo) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, next) => {
|
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, next) => {
|
||||||
requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href;
|
requestContext.endpoint = configContext.PROXY_PATH;
|
||||||
requestContext.headers["x-ms-proxy-target"] = endpoint();
|
requestContext.headers["x-ms-proxy-target"] = endpoint();
|
||||||
return next(requestContext);
|
return next(requestContext);
|
||||||
};
|
};
|
||||||
@@ -43,7 +43,12 @@ export const endpoint = () => {
|
|||||||
const location = _global.parent ? _global.parent.location : _global.location;
|
const location = _global.parent ? _global.parent.location : _global.location;
|
||||||
return configContext.EMULATOR_ENDPOINT || location.origin;
|
return configContext.EMULATOR_ENDPOINT || location.origin;
|
||||||
}
|
}
|
||||||
return userContext.endpoint || userContext?.databaseAccount?.properties?.documentEndpoint;
|
return (
|
||||||
|
userContext.endpoint ||
|
||||||
|
(userContext.databaseAccount &&
|
||||||
|
userContext.databaseAccount.properties &&
|
||||||
|
userContext.databaseAccount.properties.documentEndpoint)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getTokenFromAuthService(verb: string, resourceType: string, resourceId?: string): Promise<any> {
|
export async function getTokenFromAuthService(verb: string, resourceType: string, resourceId?: string): Promise<any> {
|
||||||
@@ -70,10 +75,7 @@ export async function getTokenFromAuthService(verb: string, resourceType: string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _client: Cosmos.CosmosClient;
|
|
||||||
|
|
||||||
export function client(): Cosmos.CosmosClient {
|
export function client(): Cosmos.CosmosClient {
|
||||||
if (_client) return _client;
|
|
||||||
const options: Cosmos.CosmosClientOptions = {
|
const options: Cosmos.CosmosClientOptions = {
|
||||||
endpoint: endpoint() || "https://cosmos.azure.com", // CosmosClient gets upset if we pass a bad URL. This should never actually get called
|
endpoint: endpoint() || "https://cosmos.azure.com", // CosmosClient gets upset if we pass a bad URL. This should never actually get called
|
||||||
key: userContext.masterKey,
|
key: userContext.masterKey,
|
||||||
@@ -87,6 +89,5 @@ export function client(): Cosmos.CosmosClient {
|
|||||||
if (configContext.PROXY_PATH !== undefined) {
|
if (configContext.PROXY_PATH !== undefined) {
|
||||||
(options as any).plugins = [{ on: "request", plugin: requestPlugin }];
|
(options as any).plugins = [{ on: "request", plugin: requestPlugin }];
|
||||||
}
|
}
|
||||||
_client = new Cosmos.CosmosClient(options);
|
return new Cosmos.CosmosClient(options);
|
||||||
return _client;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
|
|
||||||
export const getEntityName = (): string => {
|
export const getEntityName = (): string => {
|
||||||
if (userContext.apiType === "Mongo") {
|
if (userContext.defaultExperience === DefaultAccountExperienceType.MongoDB) {
|
||||||
return "document";
|
return "document";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
import { DatePicker, TextField } from "@fluentui/react";
|
|
||||||
import React, { FunctionComponent } from "react";
|
|
||||||
|
|
||||||
export interface TableEntityProps {
|
|
||||||
entityValueLabel?: string;
|
|
||||||
entityValuePlaceholder: string;
|
|
||||||
entityValue: string | Date;
|
|
||||||
isEntityTypeDate: boolean;
|
|
||||||
isEntityValueDisable?: boolean;
|
|
||||||
entityTimeValue: string;
|
|
||||||
entityValueType: string;
|
|
||||||
onEntityValueChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
|
|
||||||
onSelectDate: (date: Date | null | undefined) => void;
|
|
||||||
onEntityTimeValueChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EntityValue: FunctionComponent<TableEntityProps> = ({
|
|
||||||
entityValueLabel,
|
|
||||||
entityValuePlaceholder,
|
|
||||||
entityValue,
|
|
||||||
isEntityTypeDate,
|
|
||||||
entityTimeValue,
|
|
||||||
entityValueType,
|
|
||||||
onEntityValueChange,
|
|
||||||
onSelectDate,
|
|
||||||
isEntityValueDisable,
|
|
||||||
onEntityTimeValueChange,
|
|
||||||
}: TableEntityProps): JSX.Element => {
|
|
||||||
if (isEntityTypeDate) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DatePicker
|
|
||||||
className="addEntityDatePicker"
|
|
||||||
placeholder={entityValuePlaceholder}
|
|
||||||
value={entityValue && new Date(entityValue)}
|
|
||||||
ariaLabel={entityValuePlaceholder}
|
|
||||||
onSelectDate={onSelectDate}
|
|
||||||
disabled={isEntityValueDisable}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label={entityValueLabel && entityValueLabel}
|
|
||||||
id="entityTimeId"
|
|
||||||
autoFocus
|
|
||||||
type="time"
|
|
||||||
value={entityTimeValue}
|
|
||||||
onChange={onEntityTimeValueChange}
|
|
||||||
disabled={isEntityValueDisable}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TextField
|
|
||||||
label={entityValueLabel && entityValueLabel}
|
|
||||||
className="addEntityTextField"
|
|
||||||
id="entityValueId"
|
|
||||||
autoFocus
|
|
||||||
disabled={isEntityValueDisable}
|
|
||||||
type={entityValueType}
|
|
||||||
placeholder={entityValuePlaceholder}
|
|
||||||
value={typeof entityValue === "string" && entityValue}
|
|
||||||
onChange={onEntityValueChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
70
src/Common/HashMap.test.ts
Normal file
70
src/Common/HashMap.test.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { HashMap } from "./HashMap";
|
||||||
|
|
||||||
|
describe("HashMap", () => {
|
||||||
|
it("should test if key/val exists", () => {
|
||||||
|
const map = new HashMap<number>();
|
||||||
|
map.set("a", 123);
|
||||||
|
|
||||||
|
expect(map.has("a")).toBe(true);
|
||||||
|
expect(map.has("b")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should get object back", () => {
|
||||||
|
const map = new HashMap<string>();
|
||||||
|
map.set("a", "123");
|
||||||
|
map.set("a", "456");
|
||||||
|
|
||||||
|
expect(map.get("a")).toBe("456");
|
||||||
|
expect(map.get("a")).not.toBe("123");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the right size", () => {
|
||||||
|
const map = new HashMap<string>();
|
||||||
|
map.set("a", "123");
|
||||||
|
map.set("b", "456");
|
||||||
|
|
||||||
|
expect(map.size()).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be iterable", () => {
|
||||||
|
const map = new HashMap<number>();
|
||||||
|
map.set("a", 1);
|
||||||
|
map.set("b", 10);
|
||||||
|
map.set("c", 100);
|
||||||
|
map.set("d", 1000);
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
map.forEach((key: string, value: number) => {
|
||||||
|
i += value;
|
||||||
|
});
|
||||||
|
expect(i).toBe(1111);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be deleted", () => {
|
||||||
|
const map = new HashMap<number>();
|
||||||
|
map.set("a", 1);
|
||||||
|
map.set("b", 10);
|
||||||
|
|
||||||
|
expect(map.delete("a")).toBe(true);
|
||||||
|
expect(map.delete("c")).toBe(false);
|
||||||
|
expect(map.has("a")).toBe(false);
|
||||||
|
expect(map.has("b")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should clear", () => {
|
||||||
|
const map = new HashMap<number>();
|
||||||
|
map.set("a", 1);
|
||||||
|
map.clear();
|
||||||
|
expect(map.size()).toBe(0);
|
||||||
|
expect(map.has("a")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return all keys", () => {
|
||||||
|
const map = new HashMap<number>();
|
||||||
|
map.set("a", 1);
|
||||||
|
map.set("b", 1);
|
||||||
|
expect(map.keys()).toEqual(["a", "b"]);
|
||||||
|
map.clear();
|
||||||
|
expect(map.keys().length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
45
src/Common/HashMap.ts
Normal file
45
src/Common/HashMap.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Simple hashmap implementation that doesn't rely on ES6 Map nor polyfills
|
||||||
|
*/
|
||||||
|
export class HashMap<T> {
|
||||||
|
constructor(private container: { [key: string]: T } = {}) {}
|
||||||
|
|
||||||
|
public has(key: string): boolean {
|
||||||
|
return this.container.hasOwnProperty(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: string, value: T): void {
|
||||||
|
this.container[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: string): T {
|
||||||
|
return this.container[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public size(): number {
|
||||||
|
return Object.keys(this.container).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete(key: string): boolean {
|
||||||
|
if (this.has(key)) {
|
||||||
|
delete this.container[key];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
this.container = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public keys(): string[] {
|
||||||
|
return Object.keys(this.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
public forEach(iteratorFct: (key: string, value: T) => void) {
|
||||||
|
for (const k in this.container) {
|
||||||
|
iteratorFct(k, this.container[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { SeverityLevel } from "@microsoft/applicationinsights-web";
|
|
||||||
import { Diagnostics, MessageTypes } from "../Contracts/ExplorerContracts";
|
|
||||||
import { trackTrace } from "../Shared/appInsights";
|
|
||||||
import { sendMessage } from "./MessageHandler";
|
import { sendMessage } from "./MessageHandler";
|
||||||
|
import { Diagnostics, MessageTypes } from "../Contracts/ExplorerContracts";
|
||||||
|
import { appInsights } from "../Shared/appInsights";
|
||||||
|
import { SeverityLevel } from "@microsoft/applicationinsights-web";
|
||||||
|
|
||||||
// TODO: Move to a separate Diagnostics folder
|
// TODO: Move to a separate Diagnostics folder
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -46,7 +46,7 @@ function _logEntry(entry: Diagnostics.LogEntry): void {
|
|||||||
return SeverityLevel.Information;
|
return SeverityLevel.Information;
|
||||||
}
|
}
|
||||||
})(entry.level);
|
})(entry.level);
|
||||||
trackTrace({ message: entry.message, severityLevel }, { area: entry.area });
|
appInsights.trackTrace({ message: entry.message, severityLevel }, { area: entry.area });
|
||||||
}
|
}
|
||||||
|
|
||||||
function _generateLogEntry(
|
function _generateLogEntry(
|
||||||
|
|||||||
@@ -48,18 +48,32 @@ export function sendCachedDataMessage<TResponseDataModel>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function sendMessage(data: any): void {
|
export function sendMessage(data: any): void {
|
||||||
_sendMessage({
|
if (canSendMessage()) {
|
||||||
signature: "pcIframe",
|
// We try to find data explorer window first, then fallback to current window
|
||||||
data: data,
|
const portalChildWindow = getDataExplorerWindow(window) || window;
|
||||||
});
|
portalChildWindow.parent.postMessage(
|
||||||
|
{
|
||||||
|
signature: "pcIframe",
|
||||||
|
data: data,
|
||||||
|
},
|
||||||
|
portalChildWindow.document.referrer
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendReadyMessage(): void {
|
export function sendReadyMessage(): void {
|
||||||
_sendMessage({
|
if (canSendMessage()) {
|
||||||
signature: "pcIframe",
|
// We try to find data explorer window first, then fallback to current window
|
||||||
kind: "ready",
|
const portalChildWindow = getDataExplorerWindow(window) || window;
|
||||||
data: "ready",
|
portalChildWindow.parent.postMessage(
|
||||||
});
|
{
|
||||||
|
signature: "pcIframe",
|
||||||
|
kind: "ready",
|
||||||
|
data: "ready",
|
||||||
|
},
|
||||||
|
portalChildWindow.document.referrer
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canSendMessage(): boolean {
|
export function canSendMessage(): boolean {
|
||||||
@@ -75,17 +89,3 @@ export function runGarbageCollector() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const _sendMessage = (message: any): void => {
|
|
||||||
if (canSendMessage()) {
|
|
||||||
// Portal window can receive messages from only child windows
|
|
||||||
const portalChildWindow = getDataExplorerWindow(window) || window;
|
|
||||||
if (portalChildWindow === window) {
|
|
||||||
// Current window is a child of portal, send message to portal window
|
|
||||||
portalChildWindow.parent.postMessage(message, portalChildWindow.document.referrer || "*");
|
|
||||||
} else {
|
|
||||||
// Current window is not a child of portal, send message to the child window instead (which is data explorer)
|
|
||||||
portalChildWindow.postMessage(message, portalChildWindow.location.origin || "*");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import { configContext } from "../ConfigContext";
|
|||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||||
import { Collection } from "../Contracts/ViewModels";
|
import { Collection } from "../Contracts/ViewModels";
|
||||||
|
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||||
import { userContext } from "../UserContext";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
|
||||||
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
|
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
|
||||||
|
import { userContext } from "../UserContext";
|
||||||
import { MinimalQueryIterator } from "./IteratorUtilities";
|
import { MinimalQueryIterator } from "./IteratorUtilities";
|
||||||
import { sendMessage } from "./MessageHandler";
|
import { sendMessage } from "./MessageHandler";
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ export function queryDocuments(
|
|||||||
query: string,
|
query: string,
|
||||||
continuationToken?: string
|
continuationToken?: string
|
||||||
): Promise<QueryResponse> {
|
): Promise<QueryResponse> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||||
const params = {
|
const params = {
|
||||||
db: databaseId,
|
db: databaseId,
|
||||||
@@ -121,7 +122,7 @@ export function readDocument(
|
|||||||
collection: Collection,
|
collection: Collection,
|
||||||
documentId: DocumentId
|
documentId: DocumentId
|
||||||
): Promise<DataModels.DocumentId> {
|
): Promise<DataModels.DocumentId> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||||
const idComponents = documentId.self.split("/");
|
const idComponents = documentId.self.split("/");
|
||||||
const path = idComponents.slice(0, 4).join("/");
|
const path = idComponents.slice(0, 4).join("/");
|
||||||
@@ -167,7 +168,7 @@ export function createDocument(
|
|||||||
partitionKeyProperty: string,
|
partitionKeyProperty: string,
|
||||||
documentContent: unknown
|
documentContent: unknown
|
||||||
): Promise<DataModels.DocumentId> {
|
): Promise<DataModels.DocumentId> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||||
const params = {
|
const params = {
|
||||||
db: databaseId,
|
db: databaseId,
|
||||||
@@ -206,7 +207,7 @@ export function updateDocument(
|
|||||||
documentId: DocumentId,
|
documentId: DocumentId,
|
||||||
documentContent: string
|
documentContent: string
|
||||||
): Promise<DataModels.DocumentId> {
|
): Promise<DataModels.DocumentId> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||||
const idComponents = documentId.self.split("/");
|
const idComponents = documentId.self.split("/");
|
||||||
const path = idComponents.slice(0, 5).join("/");
|
const path = idComponents.slice(0, 5).join("/");
|
||||||
@@ -247,7 +248,7 @@ export function updateDocument(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function deleteDocument(databaseId: string, collection: Collection, documentId: DocumentId): Promise<void> {
|
export function deleteDocument(databaseId: string, collection: Collection, documentId: DocumentId): Promise<void> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||||
const idComponents = documentId.self.split("/");
|
const idComponents = documentId.self.split("/");
|
||||||
const path = idComponents.slice(0, 5).join("/");
|
const path = idComponents.slice(0, 5).join("/");
|
||||||
@@ -289,7 +290,7 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
|
|||||||
export function createMongoCollectionWithProxy(
|
export function createMongoCollectionWithProxy(
|
||||||
params: DataModels.CreateCollectionParams
|
params: DataModels.CreateCollectionParams
|
||||||
): Promise<DataModels.Collection> {
|
): Promise<DataModels.Collection> {
|
||||||
const { databaseAccount } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const shardKey: string = params.partitionKey?.paths[0];
|
const shardKey: string = params.partitionKey?.paths[0];
|
||||||
const mongoParams: DataModels.MongoParameters = {
|
const mongoParams: DataModels.MongoParameters = {
|
||||||
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
|
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
|
||||||
@@ -347,7 +348,10 @@ export function getEndpoint(): string {
|
|||||||
async function errorHandling(response: Response, action: string, params: unknown): Promise<void> {
|
async function errorHandling(response: Response, action: string, params: unknown): Promise<void> {
|
||||||
const errorMessage = await response.text();
|
const errorMessage = await response.text();
|
||||||
// Log the error where the user can see it
|
// Log the error where the user can see it
|
||||||
logConsoleError(`Error ${action}: ${errorMessage}, Payload: ${JSON.stringify(params)}`);
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
ConsoleDataType.Error,
|
||||||
|
`Error ${action}: ${errorMessage}, Payload: ${JSON.stringify(params)}`
|
||||||
|
);
|
||||||
if (response.status === HttpStatusCodes.Forbidden) {
|
if (response.status === HttpStatusCodes.Forbidden) {
|
||||||
sendMessage({ type: MessageTypes.ForbiddenError, reason: errorMessage });
|
sendMessage({ type: MessageTypes.ForbiddenError, reason: errorMessage });
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ describe("Object cache", () => {
|
|||||||
cache.set("b", 2);
|
cache.set("b", 2);
|
||||||
cache.set("c", 3);
|
cache.set("c", 3);
|
||||||
cache.set("d", 4);
|
cache.set("d", 4);
|
||||||
expect(cache.size).toBe(2);
|
expect(cache.size()).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should remove first added element to keep size at limit", () => {
|
it("should remove first added element to keep size at limit", () => {
|
||||||
|
|||||||
@@ -1,27 +1,56 @@
|
|||||||
export class ObjectCache<T> extends Map<string, T> {
|
import { HashMap } from "./HashMap";
|
||||||
constructor(private limit: number) {
|
|
||||||
|
export class ObjectCache<T> extends HashMap<T> {
|
||||||
|
private keyQueue: string[]; // Last touched key FIFO to purge cache if too big.
|
||||||
|
private maxNbElements: number;
|
||||||
|
|
||||||
|
public constructor(maxNbElements: number) {
|
||||||
super();
|
super();
|
||||||
|
this.keyQueue = [];
|
||||||
|
this.maxNbElements = maxNbElements;
|
||||||
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override get(key: string): T | undefined {
|
public clear(): void {
|
||||||
return this.touch(key);
|
super.clear();
|
||||||
|
this.keyQueue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override set(key: string, value: T): this {
|
public get(key: string): T {
|
||||||
if (this.size === this.limit) {
|
this.markKeyAsTouched(key);
|
||||||
this.delete(this.keys().next().value);
|
return super.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: string, value: T): void {
|
||||||
|
super.set(key, value);
|
||||||
|
|
||||||
|
this.markKeyAsTouched(key);
|
||||||
|
|
||||||
|
if (super.size() > this.maxNbElements && key !== this.keyQueue[0]) {
|
||||||
|
this.reduceCacheSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.touch(key, value), this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private touch(key: string, value = super.get(key)) {
|
/**
|
||||||
// Map keeps (re) insertion order according to ES6 spec
|
* Invalidate elements to keep the total number below the limit
|
||||||
if (value) {
|
*/
|
||||||
this.delete(key);
|
private reduceCacheSize(): void {
|
||||||
super.set(key, value);
|
// remove a key
|
||||||
|
const oldKey = this.keyQueue.shift();
|
||||||
|
if (oldKey) {
|
||||||
|
super.delete(oldKey);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
/**
|
||||||
|
* Bubble up this key as new.
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
private markKeyAsTouched(key: string) {
|
||||||
|
const n = this.keyQueue.indexOf(key);
|
||||||
|
if (n > -1) {
|
||||||
|
this.keyQueue.splice(n, 1);
|
||||||
|
}
|
||||||
|
this.keyQueue.push(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { configContext, Platform } from "../ConfigContext";
|
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { userContext } from "../UserContext";
|
|
||||||
import { getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
import { getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
||||||
|
import { userContext } from "../UserContext";
|
||||||
|
import { configContext, Platform } from "../ConfigContext";
|
||||||
|
|
||||||
const notificationsPath = () => {
|
const notificationsPath = () => {
|
||||||
switch (configContext.platform) {
|
switch (configContext.platform) {
|
||||||
@@ -20,7 +20,9 @@ export const fetchPortalNotifications = async (): Promise<DataModels.Notificatio
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const { databaseAccount, resourceGroup, subscriptionId } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
|
const subscriptionId = userContext.subscriptionId;
|
||||||
|
const resourceGroup = userContext.resourceGroup;
|
||||||
const url = `${configContext.BACKEND_ENDPOINT}${notificationsPath()}?accountName=${
|
const url = `${configContext.BACKEND_ENDPOINT}${notificationsPath()}?accountName=${
|
||||||
databaseAccount.name
|
databaseAccount.name
|
||||||
}&subscriptionId=${subscriptionId}&resourceGroup=${resourceGroup}`;
|
}&subscriptionId=${subscriptionId}&resourceGroup=${resourceGroup}`;
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ import * as ViewModels from "../Contracts/ViewModels";
|
|||||||
import Explorer from "../Explorer/Explorer";
|
import Explorer from "../Explorer/Explorer";
|
||||||
import DocumentsTab from "../Explorer/Tabs/DocumentsTab";
|
import DocumentsTab from "../Explorer/Tabs/DocumentsTab";
|
||||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||||
import { userContext } from "../UserContext";
|
|
||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import * as QueryUtils from "../Utils/QueryUtils";
|
import * as QueryUtils from "../Utils/QueryUtils";
|
||||||
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
||||||
|
import { userContext } from "../UserContext";
|
||||||
|
import { queryDocumentsPage } from "./dataAccess/queryDocumentsPage";
|
||||||
import { createCollection } from "./dataAccess/createCollection";
|
import { createCollection } from "./dataAccess/createCollection";
|
||||||
|
import { handleError } from "./ErrorHandlingUtils";
|
||||||
import { createDocument } from "./dataAccess/createDocument";
|
import { createDocument } from "./dataAccess/createDocument";
|
||||||
import { deleteDocument } from "./dataAccess/deleteDocument";
|
import { deleteDocument } from "./dataAccess/deleteDocument";
|
||||||
import { queryDocuments } from "./dataAccess/queryDocuments";
|
import { queryDocuments } from "./dataAccess/queryDocuments";
|
||||||
import { queryDocumentsPage } from "./dataAccess/queryDocumentsPage";
|
|
||||||
import { handleError } from "./ErrorHandlingUtils";
|
|
||||||
|
|
||||||
export class QueriesClient {
|
export class QueriesClient {
|
||||||
private static readonly PartitionKey: DataModels.PartitionKey = {
|
private static readonly PartitionKey: DataModels.PartitionKey = {
|
||||||
@@ -182,8 +182,11 @@ export class QueriesClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getResourceId(): string {
|
public getResourceId(): string {
|
||||||
const { databaseAccount, subscriptionId = "", resourceGroup = "" } = userContext;
|
const databaseAccount = userContext.databaseAccount;
|
||||||
const databaseAccountName = databaseAccount?.name || "";
|
const databaseAccountName = (databaseAccount && databaseAccount.name) || "";
|
||||||
|
const subscriptionId = userContext.subscriptionId || "";
|
||||||
|
const resourceGroup = userContext.resourceGroup || "";
|
||||||
|
|
||||||
return `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDb/databaseAccounts/${databaseAccountName}`;
|
return `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDb/databaseAccounts/${databaseAccountName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +211,7 @@ export class QueriesClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fetchQueriesQuery(): string {
|
private fetchQueriesQuery(): string {
|
||||||
if (userContext.apiType === "Mongo") {
|
if (this.container.isPreferredApiMongoDB()) {
|
||||||
return QueriesClient.FetchMongoQuery;
|
return QueriesClient.FetchMongoQuery;
|
||||||
}
|
}
|
||||||
return QueriesClient.FetchQuery;
|
return QueriesClient.FetchQuery;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export class Splitter {
|
|||||||
$(this.leftSide).resizable(splitterOptions);
|
$(this.leftSide).resizable(splitterOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onResizeStart: JQueryUI.ResizableEvent = () => {
|
private onResizeStart: JQueryUI.ResizableEvent = (e: Event, ui: JQueryUI.ResizableUIParams) => {
|
||||||
if (this.direction === SplitterDirection.Vertical) {
|
if (this.direction === SplitterDirection.Vertical) {
|
||||||
$(".ui-resizable-helper").height("100%");
|
$(".ui-resizable-helper").height("100%");
|
||||||
} else {
|
} else {
|
||||||
@@ -82,7 +82,9 @@ export class Splitter {
|
|||||||
$("iframe").css("pointer-events", "none");
|
$("iframe").css("pointer-events", "none");
|
||||||
};
|
};
|
||||||
|
|
||||||
private onResizeStop: JQueryUI.ResizableEvent = () => $("iframe").css("pointer-events", "auto");
|
private onResizeStop: JQueryUI.ResizableEvent = (e: Event, ui: JQueryUI.ResizableUIParams) => {
|
||||||
|
$("iframe").css("pointer-events", "auto");
|
||||||
|
};
|
||||||
|
|
||||||
public collapseLeft() {
|
public collapseLeft() {
|
||||||
this.lastX = $(this.splitter).position().left;
|
this.lastX = $(this.splitter).position().left;
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
import {
|
|
||||||
Dropdown,
|
|
||||||
IDropdownOption,
|
|
||||||
IDropdownStyles,
|
|
||||||
IImageProps,
|
|
||||||
Image,
|
|
||||||
IStackTokens,
|
|
||||||
Stack,
|
|
||||||
TextField,
|
|
||||||
TooltipHost,
|
|
||||||
} from "@fluentui/react";
|
|
||||||
import React, { FunctionComponent } from "react";
|
|
||||||
import DeleteIcon from "../../images/delete.svg";
|
|
||||||
import EditIcon from "../../images/Edit_entity.svg";
|
|
||||||
import { CassandraType, TableType } from "../Explorer/Tables/Constants";
|
|
||||||
import { userContext } from "../UserContext";
|
|
||||||
import { EntityValue } from "./EntityValue";
|
|
||||||
|
|
||||||
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 100 } };
|
|
||||||
|
|
||||||
export interface TableEntityProps {
|
|
||||||
entityTypeLabel?: string;
|
|
||||||
entityPropertyLabel?: string;
|
|
||||||
entityValueLabel?: string;
|
|
||||||
isDeleteOptionVisible: boolean;
|
|
||||||
entityProperty: string;
|
|
||||||
entityPropertyPlaceHolder: string;
|
|
||||||
selectedKey: string | number;
|
|
||||||
entityValuePlaceholder: string;
|
|
||||||
entityValue: string | Date;
|
|
||||||
isEntityTypeDate: boolean;
|
|
||||||
options: { key: string; text: string }[];
|
|
||||||
isPropertyTypeDisable: boolean;
|
|
||||||
entityTimeValue: string;
|
|
||||||
isEntityValueDisable?: boolean;
|
|
||||||
onDeleteEntity?: () => void;
|
|
||||||
onEditEntity?: () => void;
|
|
||||||
onEntityPropertyChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
|
|
||||||
onEntityTypeChange: (event: React.FormEvent<HTMLElement>, selectedParam: IDropdownOption) => void;
|
|
||||||
onEntityValueChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
|
|
||||||
onSelectDate: (date: Date | null | undefined) => void;
|
|
||||||
onEntityTimeValueChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
|
||||||
entityTypeLabel,
|
|
||||||
entityPropertyLabel,
|
|
||||||
isDeleteOptionVisible,
|
|
||||||
entityProperty,
|
|
||||||
selectedKey,
|
|
||||||
entityPropertyPlaceHolder,
|
|
||||||
entityValueLabel,
|
|
||||||
entityValuePlaceholder,
|
|
||||||
entityValue,
|
|
||||||
options,
|
|
||||||
isPropertyTypeDisable,
|
|
||||||
isEntityTypeDate,
|
|
||||||
entityTimeValue,
|
|
||||||
isEntityValueDisable,
|
|
||||||
onEditEntity,
|
|
||||||
onDeleteEntity,
|
|
||||||
onEntityPropertyChange,
|
|
||||||
onEntityTypeChange,
|
|
||||||
onEntityValueChange,
|
|
||||||
onSelectDate,
|
|
||||||
onEntityTimeValueChange,
|
|
||||||
}: TableEntityProps): JSX.Element => {
|
|
||||||
const imageProps: IImageProps = {
|
|
||||||
width: 16,
|
|
||||||
height: 30,
|
|
||||||
className: entityPropertyLabel ? "addRemoveIconLabel" : "addRemoveIcon",
|
|
||||||
};
|
|
||||||
|
|
||||||
const sectionStackTokens: IStackTokens = { childrenGap: 12 };
|
|
||||||
|
|
||||||
const getEntityValueType = (): string => {
|
|
||||||
const { Int, Smallint, Tinyint } = CassandraType;
|
|
||||||
const { Double, Int32, Int64 } = TableType;
|
|
||||||
|
|
||||||
if (
|
|
||||||
selectedKey === Double ||
|
|
||||||
selectedKey === Int32 ||
|
|
||||||
selectedKey === Int64 ||
|
|
||||||
selectedKey === Int ||
|
|
||||||
selectedKey === Smallint ||
|
|
||||||
selectedKey === Tinyint
|
|
||||||
) {
|
|
||||||
return "number";
|
|
||||||
}
|
|
||||||
return "string";
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Stack horizontal tokens={sectionStackTokens}>
|
|
||||||
<TextField
|
|
||||||
label={entityPropertyLabel && entityPropertyLabel}
|
|
||||||
id="entityPropertyId"
|
|
||||||
autoFocus
|
|
||||||
disabled={isPropertyTypeDisable}
|
|
||||||
placeholder={entityPropertyPlaceHolder}
|
|
||||||
value={entityProperty}
|
|
||||||
onChange={onEntityPropertyChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<Dropdown
|
|
||||||
label={entityTypeLabel && entityTypeLabel}
|
|
||||||
selectedKey={selectedKey}
|
|
||||||
onChange={onEntityTypeChange}
|
|
||||||
options={options}
|
|
||||||
disabled={isPropertyTypeDisable}
|
|
||||||
id="entityTypeId"
|
|
||||||
styles={dropdownStyles}
|
|
||||||
/>
|
|
||||||
<EntityValue
|
|
||||||
entityValueLabel={entityValueLabel}
|
|
||||||
entityValueType={getEntityValueType()}
|
|
||||||
isEntityValueDisable={isEntityValueDisable}
|
|
||||||
entityValuePlaceholder={entityValuePlaceholder}
|
|
||||||
entityValue={entityValue}
|
|
||||||
isEntityTypeDate={isEntityTypeDate}
|
|
||||||
entityTimeValue={entityTimeValue}
|
|
||||||
onEntityValueChange={onEntityValueChange}
|
|
||||||
onSelectDate={onSelectDate}
|
|
||||||
onEntityTimeValueChange={onEntityTimeValueChange}
|
|
||||||
/>
|
|
||||||
{!isEntityValueDisable && (
|
|
||||||
<TooltipHost content="Edit property" id="editTooltip">
|
|
||||||
<Image {...imageProps} src={EditIcon} alt="editEntity" id="editEntity" onClick={onEditEntity} />
|
|
||||||
</TooltipHost>
|
|
||||||
)}
|
|
||||||
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
|
|
||||||
<TooltipHost content="Delete property" id="deleteTooltip">
|
|
||||||
<Image {...imageProps} src={DeleteIcon} alt="delete entity" id="deleteEntity" onClick={onDeleteEntity} />
|
|
||||||
</TooltipHost>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ITooltipHostStyles, TooltipHost } from "@fluentui/react";
|
import { useId } from "@uifabric/react-hooks";
|
||||||
import { useId } from "@fluentui/react-hooks";
|
import { ITooltipHostStyles, TooltipHost } from "office-ui-fabric-react/lib/Tooltip";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import InfoBubble from "../../../images/info-bubble.svg";
|
import InfoBubble from "../../../images/info-bubble.svg";
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Image, Stack, TextField } from "@fluentui/react";
|
import { Image, Stack, TextField } from "office-ui-fabric-react";
|
||||||
import React, { ChangeEvent, FunctionComponent, KeyboardEvent, useRef, useState } from "react";
|
import React, { ChangeEvent, FunctionComponent, KeyboardEvent, useRef, useState } from "react";
|
||||||
import FolderIcon from "../../../images/folder_16x16.svg";
|
import FolderIcon from "../../../images/folder_16x16.svg";
|
||||||
import * as Constants from "../Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
import { Tooltip } from "../Tooltip/Tooltip";
|
import { Tooltip } from "../Tooltip";
|
||||||
|
|
||||||
interface UploadProps {
|
interface UploadProps {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
exports[`requestPlugin Emulator builds a url for emulator proxy via webpack 1`] = `
|
exports[`requestPlugin Emulator builds a url for emulator proxy via webpack 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"endpoint": "http://localhost/proxy",
|
"endpoint": "/proxy",
|
||||||
"headers": Object {
|
"headers": Object {
|
||||||
"x-ms-proxy-target": "http://localhost",
|
"x-ms-proxy-target": "http://localhost",
|
||||||
},
|
},
|
||||||
@@ -12,7 +12,7 @@ Object {
|
|||||||
|
|
||||||
exports[`requestPlugin Hosted builds a proxy URL in development 1`] = `
|
exports[`requestPlugin Hosted builds a proxy URL in development 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"endpoint": "http://localhost/proxy",
|
"endpoint": "/proxy",
|
||||||
"headers": Object {
|
"headers": Object {
|
||||||
"x-ms-proxy-target": "baz",
|
"x-ms-proxy-target": "baz",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import { JSONObject, OperationResponse } from "@azure/cosmos";
|
|
||||||
import { CollectionBase } from "../../Contracts/ViewModels";
|
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
|
||||||
|
|
||||||
export const bulkCreateDocument = async (
|
|
||||||
collection: CollectionBase,
|
|
||||||
documents: JSONObject[]
|
|
||||||
): Promise<OperationResponse[]> => {
|
|
||||||
const clearMessage = logConsoleProgress(
|
|
||||||
`Executing ${documents.length} bulk operations for container ${collection.id()}`
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await client()
|
|
||||||
.database(collection.databaseId)
|
|
||||||
.container(collection.id())
|
|
||||||
.items.bulk(
|
|
||||||
documents.map((doc) => ({ operationType: "Create", resourceBody: doc })),
|
|
||||||
{ continueOnError: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const successCount = response.filter((r) => r.statusCode === 201).length;
|
|
||||||
const throttledCount = response.filter((r) => r.statusCode === 429).length;
|
|
||||||
|
|
||||||
logConsoleInfo(
|
|
||||||
`${
|
|
||||||
documents.length
|
|
||||||
} operations completed for container ${collection.id()}. ${successCount} operations succeeded. ${throttledCount} operations throttled`
|
|
||||||
);
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error, "BulkCreateDocument", `Error bulk creating items for container ${collection.id()}`);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
clearMessage();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -2,10 +2,11 @@ jest.mock("../../Utils/arm/request");
|
|||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { CreateCollectionParams, DatabaseAccount } from "../../Contracts/DataModels";
|
import { CreateCollectionParams, DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { constructRpOptions, createCollection } from "./createCollection";
|
import { createCollection, constructRpOptions } from "./createCollection";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
|
||||||
describe("createCollection", () => {
|
describe("createCollection", () => {
|
||||||
const createCollectionParams: CreateCollectionParams = {
|
const createCollectionParams: CreateCollectionParams = {
|
||||||
@@ -21,7 +22,7 @@ describe("createCollection", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,33 @@
|
|||||||
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
import { ContainerResponse, DatabaseResponse } from "@azure/cosmos";
|
import { ContainerResponse, DatabaseResponse } from "@azure/cosmos";
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
|
||||||
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
||||||
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||||
import { AuthType } from "../../AuthType";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import { client } from "../CosmosClient";
|
||||||
import { userContext } from "../../UserContext";
|
import { createMongoCollectionWithProxy } from "../MongoProxyClient";
|
||||||
|
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import {
|
import {
|
||||||
createUpdateCassandraTable,
|
createUpdateCassandraTable,
|
||||||
getCassandraTable,
|
getCassandraTable,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import {
|
|
||||||
createUpdateGremlinGraph,
|
|
||||||
getGremlinGraph,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import {
|
import {
|
||||||
createUpdateMongoDBCollection,
|
createUpdateMongoDBCollection,
|
||||||
getMongoDBCollection,
|
getMongoDBCollection,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import {
|
||||||
|
createUpdateGremlinGraph,
|
||||||
|
getGremlinGraph,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01/types";
|
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { userContext } from "../../UserContext";
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
|
||||||
import { createMongoCollectionWithProxy } from "../MongoProxyClient";
|
|
||||||
import { createDatabase } from "./createDatabase";
|
import { createDatabase } from "./createDatabase";
|
||||||
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
|
||||||
export const createCollection = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
export const createCollection = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||||
const clearMessage = logConsoleProgress(
|
const clearMessage = logConsoleProgress(
|
||||||
@@ -45,7 +46,7 @@ export const createCollection = async (params: DataModels.CreateCollectionParams
|
|||||||
await createDatabase(createDatabaseParams);
|
await createDatabase(createDatabaseParams);
|
||||||
}
|
}
|
||||||
collection = await createCollectionWithARM(params);
|
collection = await createCollectionWithARM(params);
|
||||||
} else if (userContext.apiType === "Mongo") {
|
} else if (userContext.defaultExperience === DefaultAccountExperienceType.MongoDB) {
|
||||||
collection = await createMongoCollectionWithProxy(params);
|
collection = await createMongoCollectionWithProxy(params);
|
||||||
} else {
|
} else {
|
||||||
collection = await createCollectionWithSDK(params);
|
collection = await createCollectionWithSDK(params);
|
||||||
@@ -62,20 +63,20 @@ export const createCollection = async (params: DataModels.CreateCollectionParams
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createCollectionWithARM = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
const createCollectionWithARM = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||||
const { apiType } = userContext;
|
const defaultExperience = userContext.defaultExperience;
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
return createSqlContainer(params);
|
return createSqlContainer(params);
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
return createMongoCollection(params);
|
return createMongoCollection(params);
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
return createCassandraTable(params);
|
return createCassandraTable(params);
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
return createGraph(params);
|
return createGraph(params);
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
return createTable(params);
|
return createTable(params);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,37 @@
|
|||||||
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
import { DatabaseResponse } from "@azure/cosmos";
|
import { DatabaseResponse } from "@azure/cosmos";
|
||||||
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||||
import { AuthType } from "../../AuthType";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import {
|
||||||
import { userContext } from "../../UserContext";
|
CassandraKeyspaceCreateUpdateParameters,
|
||||||
|
GremlinDatabaseCreateUpdateParameters,
|
||||||
|
MongoDBDatabaseCreateUpdateParameters,
|
||||||
|
SqlDatabaseCreateUpdateParameters,
|
||||||
|
CreateUpdateOptions,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import {
|
import {
|
||||||
createUpdateCassandraKeyspace,
|
createUpdateCassandraKeyspace,
|
||||||
getCassandraKeyspace,
|
getCassandraKeyspace,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import {
|
|
||||||
createUpdateGremlinDatabase,
|
|
||||||
getGremlinDatabase,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import {
|
import {
|
||||||
createUpdateMongoDBDatabase,
|
createUpdateMongoDBDatabase,
|
||||||
getMongoDBDatabase,
|
getMongoDBDatabase,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
CassandraKeyspaceCreateUpdateParameters,
|
createUpdateGremlinDatabase,
|
||||||
CreateUpdateOptions,
|
getGremlinDatabase,
|
||||||
GremlinDatabaseCreateUpdateParameters,
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
MongoDBDatabaseCreateUpdateParameters,
|
|
||||||
SqlDatabaseCreateUpdateParameters,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function createDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
export async function createDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
const clearMessage = logConsoleProgress(`Creating a new database ${params.databaseId}`);
|
const clearMessage = logConsoleProgress(`Creating a new database ${params.databaseId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.apiType === "Tables") {
|
if (userContext.defaultExperience === DefaultAccountExperienceType.Table) {
|
||||||
throw new Error("Creating database resources is not allowed for tables accounts");
|
throw new Error("Creating database resources is not allowed for tables accounts");
|
||||||
}
|
}
|
||||||
const database: DataModels.Database = await (userContext.authType === AuthType.AAD && !userContext.useSDKOperations
|
const database: DataModels.Database = await (userContext.authType === AuthType.AAD && !userContext.useSDKOperations
|
||||||
@@ -48,19 +49,18 @@ export async function createDatabase(params: DataModels.CreateDatabaseParams): P
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createDatabaseWithARM(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
async function createDatabaseWithARM(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
const { apiType } = userContext;
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
switch (defaultExperience) {
|
||||||
switch (apiType) {
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
case "SQL":
|
|
||||||
return createSqlDatabase(params);
|
return createSqlDatabase(params);
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
return createMongoDatabase(params);
|
return createMongoDatabase(params);
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
return createCassandraKeyspace(params);
|
return createCassandraKeyspace(params);
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
return createGremlineDatabase(params);
|
return createGremlineDatabase(params);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import {
|
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
||||||
createUpdateSqlStoredProcedure,
|
|
||||||
getSqlStoredProcedure,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
SqlStoredProcedureCreateUpdateParameters,
|
SqlStoredProcedureCreateUpdateParameters,
|
||||||
SqlStoredProcedureResource,
|
SqlStoredProcedureResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import {
|
||||||
|
createUpdateSqlStoredProcedure,
|
||||||
|
getSqlStoredProcedure,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function createStoredProcedure(
|
export async function createStoredProcedure(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -20,7 +21,11 @@ export async function createStoredProcedure(
|
|||||||
): Promise<StoredProcedureDefinition & Resource> {
|
): Promise<StoredProcedureDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Creating stored procedure ${storedProcedure.id}`);
|
const clearMessage = logConsoleProgress(`Creating stored procedure ${storedProcedure.id}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const getResponse = await getSqlStoredProcedure(
|
const getResponse = await getSqlStoredProcedure(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { Resource, TriggerDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { Resource, TriggerDefinition } from "@azure/cosmos";
|
||||||
import {
|
import {
|
||||||
SqlTriggerCreateUpdateParameters,
|
SqlTriggerCreateUpdateParameters,
|
||||||
SqlTriggerResource,
|
SqlTriggerResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function createTrigger(
|
export async function createTrigger(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -17,7 +18,11 @@ export async function createTrigger(
|
|||||||
): Promise<TriggerDefinition & Resource> {
|
): Promise<TriggerDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
|
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const getResponse = await getSqlTrigger(
|
const getResponse = await getSqlTrigger(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import {
|
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
||||||
createUpdateSqlUserDefinedFunction,
|
|
||||||
getSqlUserDefinedFunction,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
SqlUserDefinedFunctionCreateUpdateParameters,
|
SqlUserDefinedFunctionCreateUpdateParameters,
|
||||||
SqlUserDefinedFunctionResource,
|
SqlUserDefinedFunctionResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import {
|
||||||
|
createUpdateSqlUserDefinedFunction,
|
||||||
|
getSqlUserDefinedFunction,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function createUserDefinedFunction(
|
export async function createUserDefinedFunction(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -20,7 +21,11 @@ export async function createUserDefinedFunction(
|
|||||||
): Promise<UserDefinedFunctionDefinition & Resource> {
|
): Promise<UserDefinedFunctionDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
|
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const getResponse = await getSqlUserDefinedFunction(
|
const getResponse = await getSqlUserDefinedFunction(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
jest.mock("../../Utils/arm/request");
|
jest.mock("../../Utils/arm/request");
|
||||||
jest.mock("../MessageHandler");
|
jest.mock("../MessageHandler");
|
||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
|
||||||
import { updateUserContext } from "../../UserContext";
|
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { deleteCollection } from "./deleteCollection";
|
import { deleteCollection } from "./deleteCollection";
|
||||||
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
|
||||||
describe("deleteCollection", () => {
|
describe("deleteCollection", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -14,7 +15,7 @@ describe("deleteCollection", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
|
||||||
import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
|
||||||
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
|
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Deleting container ${collectionId}`);
|
||||||
@@ -27,21 +28,23 @@ export async function deleteCollection(databaseId: string, collectionId: string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteCollectionWithARM(databaseId: string, collectionId: string): Promise<void> {
|
function deleteCollectionWithARM(databaseId: string, collectionId: string): Promise<void> {
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
return deleteSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
return deleteSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
return deleteMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
return deleteMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
return deleteCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
return deleteCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
return deleteGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
return deleteGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
return deleteTable(subscriptionId, resourceGroup, accountName, collectionId);
|
return deleteTable(subscriptionId, resourceGroup, accountName, collectionId);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
jest.mock("../../Utils/arm/request");
|
jest.mock("../../Utils/arm/request");
|
||||||
jest.mock("../MessageHandler");
|
jest.mock("../MessageHandler");
|
||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
|
||||||
import { updateUserContext } from "../../UserContext";
|
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { deleteDatabase } from "./deleteDatabase";
|
import { deleteDatabase } from "./deleteDatabase";
|
||||||
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
|
||||||
describe("deleteDatabase", () => {
|
describe("deleteDatabase", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -14,7 +15,7 @@ describe("deleteDatabase", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
|
||||||
import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import { client } from "../CosmosClient";
|
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
|
||||||
export async function deleteDatabase(databaseId: string): Promise<void> {
|
export async function deleteDatabase(databaseId: string): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting database ${databaseId}`);
|
const clearMessage = logConsoleProgress(`Deleting database ${databaseId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (userContext.apiType === "Tables") {
|
if (userContext.defaultExperience === DefaultAccountExperienceType.Table) {
|
||||||
throw new Error("Deleting database resources is not allowed for tables accounts");
|
throw new Error("Deleting database resources is not allowed for tables accounts");
|
||||||
}
|
}
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
||||||
@@ -30,19 +31,21 @@ export async function deleteDatabase(databaseId: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteDatabaseWithARM(databaseId: string): Promise<void> {
|
function deleteDatabaseWithARM(databaseId: string): Promise<void> {
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
return deleteSqlDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
return deleteSqlDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
return deleteMongoDBDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
return deleteMongoDBDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
return deleteCassandraKeyspace(subscriptionId, resourceGroup, accountName, databaseId);
|
return deleteCassandraKeyspace(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
return deleteGremlinDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
return deleteGremlinDatabase(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { deleteSqlStoredProcedure } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import { deleteSqlStoredProcedure } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function deleteStoredProcedure(
|
export async function deleteStoredProcedure(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -12,7 +13,11 @@ export async function deleteStoredProcedure(
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting stored procedure ${storedProcedureId}`);
|
const clearMessage = logConsoleProgress(`Deleting stored procedure ${storedProcedureId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
await deleteSqlStoredProcedure(
|
await deleteSqlStoredProcedure(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
userContext.resourceGroup,
|
userContext.resourceGroup,
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { deleteSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import { deleteSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function deleteTrigger(databaseId: string, collectionId: string, triggerId: string): Promise<void> {
|
export async function deleteTrigger(databaseId: string, collectionId: string, triggerId: string): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting trigger ${triggerId}`);
|
const clearMessage = logConsoleProgress(`Deleting trigger ${triggerId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
await deleteSqlTrigger(
|
await deleteSqlTrigger(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
userContext.resourceGroup,
|
userContext.resourceGroup,
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { deleteSqlUserDefinedFunction } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import { deleteSqlUserDefinedFunction } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function deleteUserDefinedFunction(databaseId: string, collectionId: string, id: string): Promise<void> {
|
export async function deleteUserDefinedFunction(databaseId: string, collectionId: string, id: string): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting user defined function ${id}`);
|
const clearMessage = logConsoleProgress(`Deleting user defined function ${id}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
await deleteSqlUserDefinedFunction(
|
await deleteSqlUserDefinedFunction(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
userContext.resourceGroup,
|
userContext.resourceGroup,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { configContext } from "../../ConfigContext";
|
|
||||||
import { userContext } from "../../UserContext";
|
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
|
import { configContext } from "../../ConfigContext";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
interface TimeSeriesData {
|
interface TimeSeriesData {
|
||||||
data: {
|
data: {
|
||||||
@@ -45,9 +45,9 @@ export const getCollectionUsageSizeInKB = async (databaseName: string, container
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
const filter = `DatabaseName eq '${databaseName}' and CollectionName eq '${containerName}'`;
|
const filter = `DatabaseName eq '${databaseName}' and CollectionName eq '${containerName}'`;
|
||||||
const metricNames = "DataUsage,IndexUsage";
|
const metricNames = "DataUsage,IndexUsage";
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/providers/microsoft.insights/metrics`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/providers/microsoft.insights/metrics`;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { readCollection } from "./readCollection";
|
import { readCollection } from "./readCollection";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
|
||||||
describe("readCollection", () => {
|
describe("readCollection", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -12,7 +13,7 @@ describe("readCollection", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { Offer, ReadCollectionOfferParams } from "../../Contracts/DataModels";
|
import { Offer, ReadCollectionOfferParams } from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { getSqlContainerThroughput } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { getMongoDBCollectionThroughput } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { getCassandraTableThroughput } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
import { getCassandraTableThroughput } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import { getGremlinGraphThroughput } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
import { getGremlinGraphThroughput } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import { getMongoDBCollectionThroughput } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { getSqlContainerThroughput } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { getTableThroughput } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
import { getTableThroughput } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
|
||||||
import { readOfferWithSDK } from "./readOfferWithSDK";
|
import { readOfferWithSDK } from "./readOfferWithSDK";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export const readCollectionOffer = async (params: ReadCollectionOfferParams): Promise<Offer> => {
|
export const readCollectionOffer = async (params: ReadCollectionOfferParams): Promise<Offer> => {
|
||||||
const clearMessage = logConsoleProgress(`Querying offer for collection ${params.collectionId}`);
|
const clearMessage = logConsoleProgress(`Querying offer for collection ${params.collectionId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
return await readCollectionOfferWithARM(params.databaseId, params.collectionId);
|
return await readCollectionOfferWithARM(params.databaseId, params.collectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,13 +33,15 @@ export const readCollectionOffer = async (params: ReadCollectionOfferParams): Pr
|
|||||||
};
|
};
|
||||||
|
|
||||||
const readCollectionOfferWithARM = async (databaseId: string, collectionId: string): Promise<Offer> => {
|
const readCollectionOfferWithARM = async (databaseId: string, collectionId: string): Promise<Offer> => {
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
let rpResponse;
|
let rpResponse;
|
||||||
try {
|
try {
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
rpResponse = await getSqlContainerThroughput(
|
rpResponse = await getSqlContainerThroughput(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroup,
|
resourceGroup,
|
||||||
@@ -43,7 +50,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
|||||||
collectionId
|
collectionId
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
rpResponse = await getMongoDBCollectionThroughput(
|
rpResponse = await getMongoDBCollectionThroughput(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroup,
|
resourceGroup,
|
||||||
@@ -52,7 +59,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
|||||||
collectionId
|
collectionId
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
rpResponse = await getCassandraTableThroughput(
|
rpResponse = await getCassandraTableThroughput(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroup,
|
resourceGroup,
|
||||||
@@ -61,7 +68,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
|||||||
collectionId
|
collectionId
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
rpResponse = await getGremlinGraphThroughput(
|
rpResponse = await getGremlinGraphThroughput(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroup,
|
resourceGroup,
|
||||||
@@ -70,11 +77,11 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
|||||||
collectionId
|
collectionId
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
rpResponse = await getTableThroughput(subscriptionId, resourceGroup, accountName, collectionId);
|
rpResponse = await getTableThroughput(subscriptionId, resourceGroup, accountName, collectionId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "NotFound") {
|
if (error.code !== "NotFound") {
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ jest.mock("../../Utils/arm/request");
|
|||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { readCollections } from "./readCollections";
|
import { readCollections } from "./readCollections";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
|
||||||
describe("readCollections", () => {
|
describe("readCollections", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -13,7 +14,7 @@ describe("readCollections", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { AuthType } from "../../AuthType";
|
||||||
import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { listTables } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
|
import { listTables } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
|
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
|
||||||
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.MongoDB &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
return await readCollectionsWithARM(databaseId);
|
return await readCollectionsWithARM(databaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,28 +35,29 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
|
|||||||
|
|
||||||
async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Collection[]> {
|
async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Collection[]> {
|
||||||
let rpResponse;
|
let rpResponse;
|
||||||
|
const subscriptionId = userContext.subscriptionId;
|
||||||
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
switch (defaultExperience) {
|
||||||
const accountName = databaseAccount.name;
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
|
|
||||||
switch (apiType) {
|
|
||||||
case "SQL":
|
|
||||||
rpResponse = await listSqlContainers(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await listSqlContainers(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
rpResponse = await listMongoDBCollections(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await listMongoDBCollections(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
rpResponse = await listCassandraTables(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await listCassandraTables(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
rpResponse = await listGremlinGraphs(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await listGremlinGraphs(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
rpResponse = await listTables(subscriptionId, resourceGroup, accountName);
|
rpResponse = await listTables(subscriptionId, resourceGroup, accountName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpResponse?.value?.map((collection) => collection.properties?.resource as DataModels.Collection);
|
return rpResponse?.value?.map((collection) => collection.properties?.resource as DataModels.Collection);
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { Offer, ReadDatabaseOfferParams } from "../../Contracts/DataModels";
|
import { Offer, ReadDatabaseOfferParams } from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { getSqlDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { getMongoDBDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { getCassandraKeyspaceThroughput } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
import { getCassandraKeyspaceThroughput } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import { getGremlinDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
import { getGremlinDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import { getMongoDBDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { getSqlDatabaseThroughput } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { readOfferWithSDK } from "./readOfferWithSDK";
|
import { readOfferWithSDK } from "./readOfferWithSDK";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export const readDatabaseOffer = async (params: ReadDatabaseOfferParams): Promise<Offer> => {
|
export const readDatabaseOffer = async (params: ReadDatabaseOfferParams): Promise<Offer> => {
|
||||||
const clearMessage = logConsoleProgress(`Querying offer for database ${params.databaseId}`);
|
const clearMessage = logConsoleProgress(`Querying offer for database ${params.databaseId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
return await readDatabaseOfferWithARM(params.databaseId);
|
return await readDatabaseOfferWithARM(params.databaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,26 +32,28 @@ export const readDatabaseOffer = async (params: ReadDatabaseOfferParams): Promis
|
|||||||
};
|
};
|
||||||
|
|
||||||
const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
|
const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
let rpResponse;
|
let rpResponse;
|
||||||
try {
|
try {
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
rpResponse = await getSqlDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await getSqlDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
rpResponse = await getMongoDBDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await getMongoDBDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
rpResponse = await getCassandraKeyspaceThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await getCassandraKeyspaceThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
rpResponse = await getGremlinDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
rpResponse = await getGremlinDatabaseThroughput(subscriptionId, resourceGroup, accountName, databaseId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "NotFound") {
|
if (error.code !== "NotFound") {
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ jest.mock("../../Utils/arm/request");
|
|||||||
jest.mock("../CosmosClient");
|
jest.mock("../CosmosClient");
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { DatabaseAccount } from "../../Contracts/DataModels";
|
import { DatabaseAccount } from "../../Contracts/DataModels";
|
||||||
import { updateUserContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { armRequest } from "../../Utils/arm/request";
|
import { armRequest } from "../../Utils/arm/request";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { readDatabases } from "./readDatabases";
|
import { readDatabases } from "./readDatabases";
|
||||||
|
import { updateUserContext } from "../../UserContext";
|
||||||
|
|
||||||
describe("readDatabases", () => {
|
describe("readDatabases", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@@ -13,7 +14,7 @@ describe("readDatabases", () => {
|
|||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
name: "test",
|
name: "test",
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
apiType: "SQL",
|
defaultExperience: DefaultAccountExperienceType.DocumentDB,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { AuthType } from "../../AuthType";
|
||||||
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function readDatabases(): Promise<DataModels.Database[]> {
|
export async function readDatabases(): Promise<DataModels.Database[]> {
|
||||||
let databases: DataModels.Database[];
|
let databases: DataModels.Database[];
|
||||||
const clearMessage = logConsoleProgress(`Querying databases`);
|
const clearMessage = logConsoleProgress(`Querying databases`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
databases = await readDatabasesWithARM();
|
databases = await readDatabasesWithARM();
|
||||||
} else {
|
} else {
|
||||||
const sdkResponse = await client().databases.readAll().fetchAll();
|
const sdkResponse = await client().databases.readAll().fetchAll();
|
||||||
@@ -29,24 +34,26 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
|
|||||||
|
|
||||||
async function readDatabasesWithARM(): Promise<DataModels.Database[]> {
|
async function readDatabasesWithARM(): Promise<DataModels.Database[]> {
|
||||||
let rpResponse;
|
let rpResponse;
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
rpResponse = await listSqlDatabases(subscriptionId, resourceGroup, accountName);
|
rpResponse = await listSqlDatabases(subscriptionId, resourceGroup, accountName);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
rpResponse = await listMongoDBDatabases(subscriptionId, resourceGroup, accountName);
|
rpResponse = await listMongoDBDatabases(subscriptionId, resourceGroup, accountName);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
rpResponse = await listCassandraKeyspaces(subscriptionId, resourceGroup, accountName);
|
rpResponse = await listCassandraKeyspaces(subscriptionId, resourceGroup, accountName);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
rpResponse = await listGremlinDatabases(subscriptionId, resourceGroup, accountName);
|
rpResponse = await listGremlinDatabases(subscriptionId, resourceGroup, accountName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpResponse?.value?.map((database) => database.properties?.resource as DataModels.Database);
|
return rpResponse?.value?.map((database) => database.properties?.resource as DataModels.Database);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { AuthType } from "../../AuthType";
|
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
import { getMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
import { getMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { MongoDBCollectionResource } from "../../Utils/arm/generatedClients/2020-04-01/types";
|
import { MongoDBCollectionResource } from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
|
||||||
export async function readMongoDBCollectionThroughRP(
|
export async function readMongoDBCollectionThroughRP(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -13,9 +13,9 @@ export async function readMongoDBCollectionThroughRP(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let collection: MongoDBCollectionResource;
|
let collection: MongoDBCollectionResource;
|
||||||
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
const accountName = databaseAccount.name;
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function readStoredProcedures(
|
export async function readStoredProcedures(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -12,7 +13,11 @@ export async function readStoredProcedures(
|
|||||||
): Promise<(StoredProcedureDefinition & Resource)[]> {
|
): Promise<(StoredProcedureDefinition & Resource)[]> {
|
||||||
const clearMessage = logConsoleProgress(`Querying stored procedures for container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Querying stored procedures for container ${collectionId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const rpResponse = await listSqlStoredProcedures(
|
const rpResponse = await listSqlStoredProcedures(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
userContext.resourceGroup,
|
userContext.resourceGroup,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { Resource, TriggerDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
import { Resource, TriggerDefinition } from "@azure/cosmos";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
import { listSqlTriggers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { listSqlTriggers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { client } from "../CosmosClient";
|
import { userContext } from "../../UserContext";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
|
||||||
export async function readTriggers(
|
export async function readTriggers(
|
||||||
@@ -12,7 +13,11 @@ export async function readTriggers(
|
|||||||
): Promise<(TriggerDefinition & Resource)[]> {
|
): Promise<(TriggerDefinition & Resource)[]> {
|
||||||
const clearMessage = logConsoleProgress(`Querying triggers for container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Querying triggers for container ${collectionId}`);
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const rpResponse = await listSqlTriggers(
|
const rpResponse = await listSqlTriggers(
|
||||||
userContext.subscriptionId,
|
userContext.subscriptionId,
|
||||||
userContext.resourceGroup,
|
userContext.resourceGroup,
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { listSqlUserDefinedFunctions } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { listSqlUserDefinedFunctions } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function readUserDefinedFunctions(
|
export async function readUserDefinedFunctions(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
collectionId: string
|
collectionId: string
|
||||||
): Promise<(UserDefinedFunctionDefinition & Resource)[]> {
|
): Promise<(UserDefinedFunctionDefinition & Resource)[]> {
|
||||||
const clearMessage = logConsoleProgress(`Querying user defined functions for container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Querying user defined functions for container ${collectionId}`);
|
||||||
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
|
||||||
try {
|
try {
|
||||||
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const rpResponse = await listSqlUserDefinedFunctions(
|
const rpResponse = await listSqlUserDefinedFunctions(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId
|
collectionId
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,43 +1,51 @@
|
|||||||
import { ContainerDefinition } from "@azure/cosmos";
|
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { Collection } from "../../Contracts/DataModels";
|
import { Collection } from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { ContainerDefinition } from "@azure/cosmos";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
import {
|
||||||
|
CreateUpdateOptions,
|
||||||
|
ExtendedResourceProperties,
|
||||||
|
MongoDBCollectionCreateUpdateParameters,
|
||||||
|
MongoDBCollectionResource,
|
||||||
|
SqlContainerCreateUpdateParameters,
|
||||||
|
SqlContainerResource,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import {
|
import {
|
||||||
createUpdateCassandraTable,
|
createUpdateCassandraTable,
|
||||||
getCassandraTable,
|
getCassandraTable,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import {
|
|
||||||
createUpdateGremlinGraph,
|
|
||||||
getGremlinGraph,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
|
||||||
import {
|
import {
|
||||||
createUpdateMongoDBCollection,
|
createUpdateMongoDBCollection,
|
||||||
getMongoDBCollection,
|
getMongoDBCollection,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
|
||||||
import {
|
import {
|
||||||
ExtendedResourceProperties,
|
createUpdateGremlinGraph,
|
||||||
MongoDBCollectionCreateUpdateParameters,
|
getGremlinGraph,
|
||||||
SqlContainerCreateUpdateParameters,
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
SqlContainerResource,
|
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function updateCollection(
|
export async function updateCollection(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
collectionId: string,
|
collectionId: string,
|
||||||
newCollection: Partial<Collection>,
|
newCollection: Collection,
|
||||||
options: RequestOptions = {}
|
options: RequestOptions = {}
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
let collection: Collection;
|
let collection: Collection;
|
||||||
const clearMessage = logConsoleProgress(`Updating container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Updating container ${collectionId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.MongoDB &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
collection = await updateCollectionWithARM(databaseId, collectionId, newCollection);
|
collection = await updateCollectionWithARM(databaseId, collectionId, newCollection);
|
||||||
} else {
|
} else {
|
||||||
const sdkResponse = await client()
|
const sdkResponse = await client()
|
||||||
@@ -61,31 +69,24 @@ export async function updateCollection(
|
|||||||
async function updateCollectionWithARM(
|
async function updateCollectionWithARM(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
collectionId: string,
|
collectionId: string,
|
||||||
newCollection: Partial<Collection>
|
newCollection: Collection
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
switch (apiType) {
|
switch (defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
return updateSqlContainer(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
return updateSqlContainer(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
return updateCassandraTable(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
return updateCassandraTable(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
return updateGremlinGraph(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
return updateGremlinGraph(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
return updateTable(collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
return updateTable(collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
case "Mongo":
|
|
||||||
return updateMongoDBCollection(
|
|
||||||
databaseId,
|
|
||||||
collectionId,
|
|
||||||
subscriptionId,
|
|
||||||
resourceGroup,
|
|
||||||
accountName,
|
|
||||||
newCollection
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ async function updateSqlContainer(
|
|||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroup: string,
|
resourceGroup: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
newCollection: Partial<Collection>
|
newCollection: Collection
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
const getResponse = await getSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
const getResponse = await getSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
@@ -114,26 +115,35 @@ async function updateSqlContainer(
|
|||||||
throw new Error(`Sql container to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`);
|
throw new Error(`Sql container to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateMongoDBCollection(
|
export async function updateMongoDBCollectionThroughRP(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
collectionId: string,
|
collectionId: string,
|
||||||
subscriptionId: string,
|
newCollection: MongoDBCollectionResource,
|
||||||
resourceGroup: string,
|
updateOptions?: CreateUpdateOptions
|
||||||
accountName: string,
|
): Promise<MongoDBCollectionResource> {
|
||||||
newCollection: Partial<Collection>
|
const subscriptionId = userContext.subscriptionId;
|
||||||
): Promise<Collection> {
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
const getResponse = await getMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
const getResponse = await getMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
const updateParams: MongoDBCollectionCreateUpdateParameters = {
|
||||||
|
properties: {
|
||||||
|
resource: newCollection,
|
||||||
|
options: updateOptions,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const updateResponse = await createUpdateMongoDBCollection(
|
const updateResponse = await createUpdateMongoDBCollection(
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroup,
|
resourceGroup,
|
||||||
accountName,
|
accountName,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
getResponse as MongoDBCollectionCreateUpdateParameters
|
updateParams
|
||||||
);
|
);
|
||||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
|
||||||
|
return updateResponse && (updateResponse.properties.resource as MongoDBCollectionResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -147,7 +157,7 @@ async function updateCassandraTable(
|
|||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroup: string,
|
resourceGroup: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
newCollection: Partial<Collection>
|
newCollection: Collection
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
const getResponse = await getCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
const getResponse = await getCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
@@ -174,7 +184,7 @@ async function updateGremlinGraph(
|
|||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroup: string,
|
resourceGroup: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
newCollection: Partial<Collection>
|
newCollection: Collection
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
const getResponse = await getGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
const getResponse = await getGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
@@ -198,7 +208,7 @@ async function updateTable(
|
|||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroup: string,
|
resourceGroup: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
newCollection: Partial<Collection>
|
newCollection: Collection
|
||||||
): Promise<Collection> {
|
): Promise<Collection> {
|
||||||
const getResponse = await getTable(subscriptionId, resourceGroup, accountName, collectionId);
|
const getResponse = await getTable(subscriptionId, resourceGroup, accountName, collectionId);
|
||||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
|||||||
@@ -1,53 +1,54 @@
|
|||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
import { HttpHeaders } from "../Constants";
|
||||||
|
import { Offer, SDKOfferDefinition, UpdateOfferParams } from "../../Contracts/DataModels";
|
||||||
import { OfferDefinition } from "@azure/cosmos";
|
import { OfferDefinition } from "@azure/cosmos";
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import { AuthType } from "../../AuthType";
|
import { ThroughputSettingsUpdateParameters } from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { Offer, SDKOfferDefinition, UpdateOfferParams } from "../../Contracts/DataModels";
|
import { client } from "../CosmosClient";
|
||||||
import { userContext } from "../../UserContext";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { parseSDKOfferResponse } from "../OfferUtility";
|
||||||
|
import { readCollectionOffer } from "./readCollectionOffer";
|
||||||
|
import { readDatabaseOffer } from "./readDatabaseOffer";
|
||||||
import {
|
import {
|
||||||
|
updateSqlDatabaseThroughput,
|
||||||
|
migrateSqlDatabaseToAutoscale,
|
||||||
|
migrateSqlDatabaseToManualThroughput,
|
||||||
|
migrateSqlContainerToAutoscale,
|
||||||
|
migrateSqlContainerToManualThroughput,
|
||||||
|
updateSqlContainerThroughput,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import {
|
||||||
|
updateCassandraKeyspaceThroughput,
|
||||||
migrateCassandraKeyspaceToAutoscale,
|
migrateCassandraKeyspaceToAutoscale,
|
||||||
migrateCassandraKeyspaceToManualThroughput,
|
migrateCassandraKeyspaceToManualThroughput,
|
||||||
migrateCassandraTableToAutoscale,
|
migrateCassandraTableToAutoscale,
|
||||||
migrateCassandraTableToManualThroughput,
|
migrateCassandraTableToManualThroughput,
|
||||||
updateCassandraKeyspaceThroughput,
|
|
||||||
updateCassandraTableThroughput,
|
updateCassandraTableThroughput,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
import {
|
import {
|
||||||
|
updateMongoDBDatabaseThroughput,
|
||||||
|
migrateMongoDBDatabaseToAutoscale,
|
||||||
|
migrateMongoDBDatabaseToManualThroughput,
|
||||||
|
migrateMongoDBCollectionToAutoscale,
|
||||||
|
migrateMongoDBCollectionToManualThroughput,
|
||||||
|
updateMongoDBCollectionThroughput,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import {
|
||||||
|
updateGremlinDatabaseThroughput,
|
||||||
migrateGremlinDatabaseToAutoscale,
|
migrateGremlinDatabaseToAutoscale,
|
||||||
migrateGremlinDatabaseToManualThroughput,
|
migrateGremlinDatabaseToManualThroughput,
|
||||||
migrateGremlinGraphToAutoscale,
|
migrateGremlinGraphToAutoscale,
|
||||||
migrateGremlinGraphToManualThroughput,
|
migrateGremlinGraphToManualThroughput,
|
||||||
updateGremlinDatabaseThroughput,
|
|
||||||
updateGremlinGraphThroughput,
|
updateGremlinGraphThroughput,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
import {
|
import { userContext } from "../../UserContext";
|
||||||
migrateMongoDBCollectionToAutoscale,
|
|
||||||
migrateMongoDBCollectionToManualThroughput,
|
|
||||||
migrateMongoDBDatabaseToAutoscale,
|
|
||||||
migrateMongoDBDatabaseToManualThroughput,
|
|
||||||
updateMongoDBCollectionThroughput,
|
|
||||||
updateMongoDBDatabaseThroughput,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
|
||||||
import {
|
|
||||||
migrateSqlContainerToAutoscale,
|
|
||||||
migrateSqlContainerToManualThroughput,
|
|
||||||
migrateSqlDatabaseToAutoscale,
|
|
||||||
migrateSqlDatabaseToManualThroughput,
|
|
||||||
updateSqlContainerThroughput,
|
|
||||||
updateSqlDatabaseThroughput,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
migrateTableToAutoscale,
|
migrateTableToAutoscale,
|
||||||
migrateTableToManualThroughput,
|
migrateTableToManualThroughput,
|
||||||
updateTableThroughput,
|
updateTableThroughput,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
} from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
import { ThroughputSettingsUpdateParameters } from "../../Utils/arm/generatedClients/2020-04-01/types";
|
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { HttpHeaders } from "../Constants";
|
|
||||||
import { client } from "../CosmosClient";
|
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
|
||||||
import { parseSDKOfferResponse } from "../OfferUtility";
|
|
||||||
import { readCollectionOffer } from "./readCollectionOffer";
|
|
||||||
import { readDatabaseOffer } from "./readDatabaseOffer";
|
|
||||||
|
|
||||||
export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> => {
|
export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> => {
|
||||||
let updatedOffer: Offer;
|
let updatedOffer: Offer;
|
||||||
@@ -60,7 +61,7 @@ export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> =>
|
|||||||
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
||||||
if (params.collectionId) {
|
if (params.collectionId) {
|
||||||
updatedOffer = await updateCollectionOfferWithARM(params);
|
updatedOffer = await updateCollectionOfferWithARM(params);
|
||||||
} else if (userContext.apiType === "Tables") {
|
} else if (userContext.defaultExperience === DefaultAccountExperienceType.Table) {
|
||||||
// update table's database offer with SDK since RP doesn't support it
|
// update table's database offer with SDK since RP doesn't support it
|
||||||
updatedOffer = await updateOfferWithSDK(params);
|
updatedOffer = await updateOfferWithSDK(params);
|
||||||
} else {
|
} else {
|
||||||
@@ -81,24 +82,24 @@ export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> =>
|
|||||||
|
|
||||||
const updateCollectionOfferWithARM = async (params: UpdateOfferParams): Promise<Offer> => {
|
const updateCollectionOfferWithARM = async (params: UpdateOfferParams): Promise<Offer> => {
|
||||||
try {
|
try {
|
||||||
switch (userContext.apiType) {
|
switch (userContext.defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
await updateSqlContainerOffer(params);
|
await updateSqlContainerOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
await updateMongoCollectionOffer(params);
|
await updateMongoCollectionOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
await updateCassandraTableOffer(params);
|
await updateCassandraTableOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
await updateGremlinGraphOffer(params);
|
await updateGremlinGraphOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Tables":
|
case DefaultAccountExperienceType.Table:
|
||||||
await updateTableOffer(params);
|
await updateTableOffer(params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${userContext.apiType}`);
|
throw new Error(`Unsupported default experience type: ${userContext.defaultExperience}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "MethodNotAllowed") {
|
if (error.code !== "MethodNotAllowed") {
|
||||||
@@ -115,21 +116,21 @@ const updateCollectionOfferWithARM = async (params: UpdateOfferParams): Promise<
|
|||||||
|
|
||||||
const updateDatabaseOfferWithARM = async (params: UpdateOfferParams): Promise<Offer> => {
|
const updateDatabaseOfferWithARM = async (params: UpdateOfferParams): Promise<Offer> => {
|
||||||
try {
|
try {
|
||||||
switch (userContext.apiType) {
|
switch (userContext.defaultExperience) {
|
||||||
case "SQL":
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
await updateSqlDatabaseOffer(params);
|
await updateSqlDatabaseOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Mongo":
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
await updateMongoDatabaseOffer(params);
|
await updateMongoDatabaseOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Cassandra":
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
await updateCassandraKeyspaceOffer(params);
|
await updateCassandraKeyspaceOffer(params);
|
||||||
break;
|
break;
|
||||||
case "Gremlin":
|
case DefaultAccountExperienceType.Graph:
|
||||||
await updateGremlinDatabaseOffer(params);
|
await updateGremlinDatabaseOffer(params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported default experience type: ${userContext.apiType}`);
|
throw new Error(`Unsupported default experience type: ${userContext.defaultExperience}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code !== "MethodNotAllowed") {
|
if (error.code !== "MethodNotAllowed") {
|
||||||
@@ -144,8 +145,9 @@ const updateDatabaseOfferWithARM = async (params: UpdateOfferParams): Promise<Of
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateSqlContainerToAutoscale(
|
await migrateSqlContainerToAutoscale(
|
||||||
@@ -177,8 +179,9 @@ const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateMongoDBCollectionToAutoscale(
|
await migrateMongoDBCollectionToAutoscale(
|
||||||
@@ -210,8 +213,9 @@ const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<vo
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateCassandraTableToAutoscale(
|
await migrateCassandraTableToAutoscale(
|
||||||
@@ -243,8 +247,9 @@ const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<voi
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateGremlinGraphToAutoscale(
|
await migrateGremlinGraphToAutoscale(
|
||||||
@@ -276,8 +281,9 @@ const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateTableOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateTableOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateTableToAutoscale(subscriptionId, resourceGroup, accountName, params.collectionId);
|
await migrateTableToAutoscale(subscriptionId, resourceGroup, accountName, params.collectionId);
|
||||||
@@ -290,8 +296,9 @@ const updateTableOffer = async (params: UpdateOfferParams): Promise<void> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateSqlDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateSqlDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateSqlDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
await migrateSqlDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
||||||
@@ -304,8 +311,9 @@ const updateSqlDatabaseOffer = async (params: UpdateOfferParams): Promise<void>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateMongoDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateMongoDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateMongoDBDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
await migrateMongoDBDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
||||||
@@ -318,8 +326,9 @@ const updateMongoDatabaseOffer = async (params: UpdateOfferParams): Promise<void
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateCassandraKeyspaceOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateCassandraKeyspaceOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateCassandraKeyspaceToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
await migrateCassandraKeyspaceToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
||||||
@@ -332,8 +341,9 @@ const updateCassandraKeyspaceOffer = async (params: UpdateOfferParams): Promise<
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateGremlinDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
const updateGremlinDatabaseOffer = async (params: UpdateOfferParams): Promise<void> => {
|
||||||
const { subscriptionId, resourceGroup, databaseAccount } = userContext;
|
const subscriptionId = userContext.subscriptionId;
|
||||||
const accountName = databaseAccount.name;
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
|
||||||
if (params.migrateToAutoPilot) {
|
if (params.migrateToAutoPilot) {
|
||||||
await migrateGremlinDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
await migrateGremlinDatabaseToAutoscale(subscriptionId, resourceGroup, accountName, params.databaseId);
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import {
|
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
|
||||||
createUpdateSqlStoredProcedure,
|
|
||||||
getSqlStoredProcedure,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
SqlStoredProcedureCreateUpdateParameters,
|
SqlStoredProcedureCreateUpdateParameters,
|
||||||
SqlStoredProcedureResource,
|
SqlStoredProcedureResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import {
|
||||||
|
createUpdateSqlStoredProcedure,
|
||||||
|
getSqlStoredProcedure,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function updateStoredProcedure(
|
export async function updateStoredProcedure(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -20,13 +21,15 @@ export async function updateStoredProcedure(
|
|||||||
): Promise<StoredProcedureDefinition & Resource> {
|
): Promise<StoredProcedureDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Updating stored procedure ${storedProcedure.id}`);
|
const clearMessage = logConsoleProgress(`Updating stored procedure ${storedProcedure.id}`);
|
||||||
try {
|
try {
|
||||||
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const getResponse = await getSqlStoredProcedure(
|
const getResponse = await getSqlStoredProcedure(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
storedProcedure.id
|
storedProcedure.id
|
||||||
@@ -40,9 +43,9 @@ export async function updateStoredProcedure(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const rpResponse = await createUpdateSqlStoredProcedure(
|
const rpResponse = await createUpdateSqlStoredProcedure(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
storedProcedure.id,
|
storedProcedure.id,
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { TriggerDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
SqlTriggerCreateUpdateParameters,
|
SqlTriggerCreateUpdateParameters,
|
||||||
SqlTriggerResource,
|
SqlTriggerResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { TriggerDefinition } from "@azure/cosmos";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function updateTrigger(
|
export async function updateTrigger(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -16,13 +17,16 @@ export async function updateTrigger(
|
|||||||
trigger: TriggerDefinition
|
trigger: TriggerDefinition
|
||||||
): Promise<TriggerDefinition> {
|
): Promise<TriggerDefinition> {
|
||||||
const clearMessage = logConsoleProgress(`Updating trigger ${trigger.id}`);
|
const clearMessage = logConsoleProgress(`Updating trigger ${trigger.id}`);
|
||||||
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
|
||||||
try {
|
try {
|
||||||
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const getResponse = await getSqlTrigger(
|
const getResponse = await getSqlTrigger(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
trigger.id
|
trigger.id
|
||||||
@@ -36,9 +40,9 @@ export async function updateTrigger(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const rpResponse = await createUpdateSqlTrigger(
|
const rpResponse = await createUpdateSqlTrigger(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
trigger.id,
|
trigger.id,
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import { userContext } from "../../UserContext";
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
import {
|
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
|
||||||
createUpdateSqlUserDefinedFunction,
|
|
||||||
getSqlUserDefinedFunction,
|
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
|
||||||
import {
|
import {
|
||||||
SqlUserDefinedFunctionCreateUpdateParameters,
|
SqlUserDefinedFunctionCreateUpdateParameters,
|
||||||
SqlUserDefinedFunctionResource,
|
SqlUserDefinedFunctionResource,
|
||||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
|
import {
|
||||||
|
createUpdateSqlUserDefinedFunction,
|
||||||
|
getSqlUserDefinedFunction,
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export async function updateUserDefinedFunction(
|
export async function updateUserDefinedFunction(
|
||||||
databaseId: string,
|
databaseId: string,
|
||||||
@@ -19,13 +20,16 @@ export async function updateUserDefinedFunction(
|
|||||||
userDefinedFunction: UserDefinedFunctionDefinition
|
userDefinedFunction: UserDefinedFunctionDefinition
|
||||||
): Promise<UserDefinedFunctionDefinition & Resource> {
|
): Promise<UserDefinedFunctionDefinition & Resource> {
|
||||||
const clearMessage = logConsoleProgress(`Updating user defined function ${userDefinedFunction.id}`);
|
const clearMessage = logConsoleProgress(`Updating user defined function ${userDefinedFunction.id}`);
|
||||||
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
|
||||||
try {
|
try {
|
||||||
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
|
if (
|
||||||
|
userContext.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience === DefaultAccountExperienceType.DocumentDB
|
||||||
|
) {
|
||||||
const getResponse = await getSqlUserDefinedFunction(
|
const getResponse = await getSqlUserDefinedFunction(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
userDefinedFunction.id
|
userDefinedFunction.id
|
||||||
@@ -39,9 +43,9 @@ export async function updateUserDefinedFunction(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const rpResponse = await createUpdateSqlUserDefinedFunction(
|
const rpResponse = await createUpdateSqlUserDefinedFunction(
|
||||||
subscriptionId,
|
userContext.subscriptionId,
|
||||||
resourceGroup,
|
userContext.resourceGroup,
|
||||||
databaseAccount.name,
|
userContext.databaseAccount.name,
|
||||||
databaseId,
|
databaseId,
|
||||||
collectionId,
|
collectionId,
|
||||||
userDefinedFunction.id,
|
userDefinedFunction.id,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ export interface ConfigContext {
|
|||||||
GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it.
|
GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it.
|
||||||
hostedExplorerURL: string;
|
hostedExplorerURL: string;
|
||||||
armAPIVersion?: string;
|
armAPIVersion?: string;
|
||||||
allowedJunoOrigins: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default configuration
|
// Default configuration
|
||||||
@@ -54,13 +53,6 @@ let configContext: Readonly<ConfigContext> = {
|
|||||||
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306
|
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306
|
||||||
JUNO_ENDPOINT: "https://tools.cosmos.azure.com",
|
JUNO_ENDPOINT: "https://tools.cosmos.azure.com",
|
||||||
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
||||||
allowedJunoOrigins: [
|
|
||||||
"https://juno-test.documents-dev.windows-int.net",
|
|
||||||
"https://juno-test2.documents-dev.windows-int.net",
|
|
||||||
"https://tools.cosmos.azure.com",
|
|
||||||
"https://tools-staging.cosmos.azure.com",
|
|
||||||
"https://localhost",
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function resetConfigContext(): void {
|
export function resetConfigContext(): void {
|
||||||
@@ -94,18 +86,13 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
|||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
try {
|
try {
|
||||||
const { allowedParentFrameOrigins, allowedJunoOrigins, ...externalConfig } = await response.json();
|
const { allowedParentFrameOrigins, ...externalConfig } = await response.json();
|
||||||
Object.assign(configContext, externalConfig);
|
Object.assign(configContext, externalConfig);
|
||||||
if (allowedParentFrameOrigins && allowedParentFrameOrigins.length > 0) {
|
if (allowedParentFrameOrigins && allowedParentFrameOrigins.length > 0) {
|
||||||
updateConfigContext({
|
updateConfigContext({
|
||||||
allowedParentFrameOrigins: [...configContext.allowedParentFrameOrigins, ...allowedParentFrameOrigins],
|
allowedParentFrameOrigins: [...configContext.allowedParentFrameOrigins, ...allowedParentFrameOrigins],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (allowedJunoOrigins && allowedJunoOrigins.length > 0) {
|
|
||||||
updateConfigContext({
|
|
||||||
allowedJunoOrigins: [...configContext.allowedJunoOrigins, ...allowedJunoOrigins],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Unable to parse json in config file");
|
console.error("Unable to parse json in config file");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
export enum TabKind {
|
export enum TabKind {
|
||||||
SQLDocuments,
|
SQLDocuments,
|
||||||
MongoDocuments,
|
MongoDocuments,
|
||||||
SchemaAnalyzer,
|
|
||||||
TableEntities,
|
TableEntities,
|
||||||
Graph,
|
Graph,
|
||||||
SQLQuery,
|
SQLQuery,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface DatabaseAccount {
|
|||||||
location: string;
|
location: string;
|
||||||
type: string;
|
type: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
|
tags: any;
|
||||||
properties: DatabaseAccountExtendedProperties;
|
properties: DatabaseAccountExtendedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +121,6 @@ export interface ISchemaRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Collection extends Resource {
|
export interface Collection extends Resource {
|
||||||
// Only in Mongo collections loaded via ARM
|
|
||||||
shardKey?: {
|
|
||||||
[key: string]: string;
|
|
||||||
};
|
|
||||||
defaultTtl?: number;
|
defaultTtl?: number;
|
||||||
indexingPolicy?: IndexingPolicy;
|
indexingPolicy?: IndexingPolicy;
|
||||||
partitionKey?: PartitionKey;
|
partitionKey?: PartitionKey;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import StoredProcedure from "../Explorer/Tree/StoredProcedure";
|
|||||||
import Trigger from "../Explorer/Tree/Trigger";
|
import Trigger from "../Explorer/Tree/Trigger";
|
||||||
import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction";
|
import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction";
|
||||||
import { SelfServeType } from "../SelfServe/SelfServeUtils";
|
import { SelfServeType } from "../SelfServe/SelfServeUtils";
|
||||||
|
import { UploadDetails } from "../workers/upload/definitions";
|
||||||
import * as DataModels from "./DataModels";
|
import * as DataModels from "./DataModels";
|
||||||
import { SubscriptionType } from "./SubscriptionType";
|
import { SubscriptionType } from "./SubscriptionType";
|
||||||
|
|
||||||
@@ -22,14 +23,6 @@ export interface TokenProvider {
|
|||||||
getAuthHeader(): Promise<Headers>;
|
getAuthHeader(): Promise<Headers>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UploadDetailsRecord {
|
|
||||||
fileName: string;
|
|
||||||
numSucceeded: number;
|
|
||||||
numFailed: number;
|
|
||||||
numThrottled: number;
|
|
||||||
errors: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface QueryResultsMetadata {
|
export interface QueryResultsMetadata {
|
||||||
hasMoreResults: boolean;
|
hasMoreResults: boolean;
|
||||||
firstItemIndex: number;
|
firstItemIndex: number;
|
||||||
@@ -141,7 +134,6 @@ export interface Collection extends CollectionBase {
|
|||||||
onTableEntitiesClick(): void;
|
onTableEntitiesClick(): void;
|
||||||
onGraphDocumentsClick(): void;
|
onGraphDocumentsClick(): void;
|
||||||
onMongoDBDocumentsClick(): void;
|
onMongoDBDocumentsClick(): void;
|
||||||
onSchemaAnalyzerClick(): void;
|
|
||||||
openTab(): void;
|
openTab(): void;
|
||||||
|
|
||||||
onSettingsClick: () => Promise<void>;
|
onSettingsClick: () => Promise<void>;
|
||||||
@@ -182,7 +174,7 @@ export interface Collection extends CollectionBase {
|
|||||||
|
|
||||||
onDragOver(source: Collection, event: { originalEvent: DragEvent }): void;
|
onDragOver(source: Collection, event: { originalEvent: DragEvent }): void;
|
||||||
onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
|
onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
|
||||||
uploadFiles(fileList: FileList): Promise<{ data: UploadDetailsRecord[] }>;
|
uploadFiles(fileList: FileList): Promise<UploadDetails>;
|
||||||
|
|
||||||
getLabel(): string;
|
getLabel(): string;
|
||||||
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
|
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
|
||||||
@@ -277,6 +269,7 @@ export interface TabOptions {
|
|||||||
tabKind: CollectionTabKind;
|
tabKind: CollectionTabKind;
|
||||||
title: string;
|
title: string;
|
||||||
tabPath: string;
|
tabPath: string;
|
||||||
|
isActive: ko.Observable<boolean>;
|
||||||
hashLocation: string;
|
hashLocation: string;
|
||||||
onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void;
|
onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void;
|
||||||
isTabsContentExpanded?: ko.Observable<boolean>;
|
isTabsContentExpanded?: ko.Observable<boolean>;
|
||||||
@@ -367,7 +360,6 @@ export enum CollectionTabKind {
|
|||||||
Schema = 19,
|
Schema = 19,
|
||||||
CollectionSettingsV2 = 20,
|
CollectionSettingsV2 = 20,
|
||||||
DatabaseSettingsV2 = 21,
|
DatabaseSettingsV2 = 21,
|
||||||
SchemaAnalyzer = 22,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TerminalKind {
|
export enum TerminalKind {
|
||||||
@@ -398,9 +390,6 @@ export interface DataExplorerInputsFrame {
|
|||||||
dataExplorerVersion?: string;
|
dataExplorerVersion?: string;
|
||||||
defaultCollectionThroughput?: CollectionCreationDefaults;
|
defaultCollectionThroughput?: CollectionCreationDefaults;
|
||||||
flights?: readonly string[];
|
flights?: readonly string[];
|
||||||
features?: {
|
|
||||||
[key: string]: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelfServeFrameInputs {
|
export interface SelfServeFrameInputs {
|
||||||
|
|||||||
8
src/DefaultAccountExperienceType.ts
Normal file
8
src/DefaultAccountExperienceType.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export enum DefaultAccountExperienceType {
|
||||||
|
DocumentDB = "DocumentDB",
|
||||||
|
Graph = "Graph",
|
||||||
|
MongoDB = "MongoDB",
|
||||||
|
Table = "Table",
|
||||||
|
Cassandra = "Cassandra",
|
||||||
|
ApiForMongoDB = "Azure Cosmos DB for MongoDB API",
|
||||||
|
}
|
||||||
7
src/Definitions/worker.d.ts
vendored
Normal file
7
src/Definitions/worker.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
declare module "worker-loader!*" {
|
||||||
|
class WebpackWorker extends Worker {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WebpackWorker;
|
||||||
|
}
|
||||||
@@ -8,6 +8,10 @@ describe("Component Registerer", () => {
|
|||||||
expect(ko.components.isRegistered("input-typeahead")).toBe(true);
|
expect(ko.components.isRegistered("input-typeahead")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should register new-vertex-form component", () => {
|
||||||
|
expect(ko.components.isRegistered("new-vertex-form")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should register error-display component", () => {
|
it("should register error-display component", () => {
|
||||||
expect(ko.components.isRegistered("error-display")).toBe(true);
|
expect(ko.components.isRegistered("error-display")).toBe(true);
|
||||||
});
|
});
|
||||||
@@ -20,14 +24,83 @@ describe("Component Registerer", () => {
|
|||||||
expect(ko.components.isRegistered("json-editor")).toBe(true);
|
expect(ko.components.isRegistered("json-editor")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should register documents-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("documents-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register stored-procedure-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("stored-procedure-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register trigger-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("trigger-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register user-defined-function-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("user-defined-function-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register settings-tab-v2 component", () => {
|
||||||
|
expect(ko.components.isRegistered("database-settings-tab-v2")).toBe(true);
|
||||||
|
expect(ko.components.isRegistered("collection-settings-tab-v2")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register query-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("query-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register tables-query-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("tables-query-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register graph-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("graph-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register notebookv2-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("notebookv2-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register terminal-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("terminal-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register mongo-shell-tab component", () => {
|
||||||
|
expect(ko.components.isRegistered("mongo-shell-tab")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should registeradd-collection-pane component", () => {
|
it("should registeradd-collection-pane component", () => {
|
||||||
expect(ko.components.isRegistered("add-collection-pane")).toBe(true);
|
expect(ko.components.isRegistered("add-collection-pane")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should register delete-collection-confirmation-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("delete-collection-confirmation-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register save-query-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("save-query-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register browse-queries-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("browse-queries-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register graph-new-vertex-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("graph-new-vertex-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should register graph-styling-pane component", () => {
|
it("should register graph-styling-pane component", () => {
|
||||||
expect(ko.components.isRegistered("graph-styling-pane")).toBe(true);
|
expect(ko.components.isRegistered("graph-styling-pane")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should register string-input-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("string-input-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should register setup-notebooks-pane component", () => {
|
||||||
|
expect(ko.components.isRegistered("setup-notebooks-pane")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should register dynamic-list component", () => {
|
it("should register dynamic-list component", () => {
|
||||||
expect(ko.components.isRegistered("dynamic-list")).toBe(true);
|
expect(ko.components.isRegistered("dynamic-list")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,9 +7,27 @@ import { InputTypeaheadComponent } from "./Controls/InputTypeahead/InputTypeahea
|
|||||||
import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent";
|
import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent";
|
||||||
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
|
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
|
||||||
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
|
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
|
||||||
|
import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponent";
|
||||||
import * as PaneComponents from "./Panes/PaneComponents";
|
import * as PaneComponents from "./Panes/PaneComponents";
|
||||||
|
import ConflictsTab from "./Tabs/ConflictsTab";
|
||||||
|
import DatabaseSettingsTab from "./Tabs/DatabaseSettingsTab";
|
||||||
|
import DocumentsTab from "./Tabs/DocumentsTab";
|
||||||
|
import GalleryTab from "./Tabs/GalleryTab";
|
||||||
|
import GraphTab from "./Tabs/GraphTab";
|
||||||
|
import MongoShellTab from "./Tabs/MongoShellTab";
|
||||||
|
import NotebookTabV2 from "./Tabs/NotebookV2Tab";
|
||||||
|
import NotebookViewerTab from "./Tabs/NotebookViewerTab";
|
||||||
|
import QueryTab from "./Tabs/QueryTab";
|
||||||
|
import QueryTablesTab from "./Tabs/QueryTablesTab";
|
||||||
|
import { DatabaseSettingsTabV2, SettingsTabV2 } from "./Tabs/SettingsTabV2";
|
||||||
|
import StoredProcedureTab from "./Tabs/StoredProcedureTab";
|
||||||
|
import TabsManagerTemplate from "./Tabs/TabsManager.html";
|
||||||
|
import TerminalTab from "./Tabs/TerminalTab";
|
||||||
|
import TriggerTab from "./Tabs/TriggerTab";
|
||||||
|
import UserDefinedFunctionTab from "./Tabs/UserDefinedFunctionTab";
|
||||||
|
|
||||||
ko.components.register("input-typeahead", new InputTypeaheadComponent());
|
ko.components.register("input-typeahead", new InputTypeaheadComponent());
|
||||||
|
ko.components.register("new-vertex-form", NewVertexComponent);
|
||||||
ko.components.register("error-display", new ErrorDisplayComponent());
|
ko.components.register("error-display", new ErrorDisplayComponent());
|
||||||
ko.components.register("graph-style", GraphStyleComponent);
|
ko.components.register("graph-style", GraphStyleComponent);
|
||||||
ko.components.register("editor", new EditorComponent());
|
ko.components.register("editor", new EditorComponent());
|
||||||
@@ -17,9 +35,46 @@ ko.components.register("json-editor", new JsonEditorComponent());
|
|||||||
ko.components.register("diff-editor", new DiffEditorComponent());
|
ko.components.register("diff-editor", new DiffEditorComponent());
|
||||||
ko.components.register("dynamic-list", DynamicListComponent);
|
ko.components.register("dynamic-list", DynamicListComponent);
|
||||||
ko.components.register("throughput-input-autopilot-v3", ThroughputInputComponentAutoPilotV3);
|
ko.components.register("throughput-input-autopilot-v3", ThroughputInputComponentAutoPilotV3);
|
||||||
|
ko.components.register("tabs-manager", { template: TabsManagerTemplate });
|
||||||
|
|
||||||
|
// Collection Tabs
|
||||||
|
[
|
||||||
|
DocumentsTab,
|
||||||
|
StoredProcedureTab,
|
||||||
|
TriggerTab,
|
||||||
|
UserDefinedFunctionTab,
|
||||||
|
SettingsTabV2,
|
||||||
|
QueryTab,
|
||||||
|
QueryTablesTab,
|
||||||
|
GraphTab,
|
||||||
|
MongoShellTab,
|
||||||
|
ConflictsTab,
|
||||||
|
NotebookTabV2,
|
||||||
|
TerminalTab,
|
||||||
|
GalleryTab,
|
||||||
|
NotebookViewerTab,
|
||||||
|
DatabaseSettingsTab,
|
||||||
|
DatabaseSettingsTabV2,
|
||||||
|
].forEach(({ component: { name, template } }) => ko.components.register(name, { template }));
|
||||||
|
|
||||||
// Panes
|
// Panes
|
||||||
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());
|
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());
|
||||||
ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent());
|
ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent());
|
||||||
|
ko.components.register(
|
||||||
|
"delete-collection-confirmation-pane",
|
||||||
|
new PaneComponents.DeleteCollectionConfirmationPaneComponent()
|
||||||
|
);
|
||||||
|
|
||||||
|
ko.components.register("graph-new-vertex-pane", new PaneComponents.GraphNewVertexPaneComponent());
|
||||||
ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPaneComponent());
|
ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPaneComponent());
|
||||||
|
ko.components.register("table-add-entity-pane", new PaneComponents.TableAddEntityPaneComponent());
|
||||||
|
ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEntityPaneComponent());
|
||||||
|
ko.components.register("table-column-options-pane", new PaneComponents.TableColumnOptionsPaneComponent());
|
||||||
|
ko.components.register("table-query-select-pane", new PaneComponents.TableQuerySelectPaneComponent());
|
||||||
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
|
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
|
||||||
|
ko.components.register("load-query-pane", new PaneComponents.LoadQueryPaneComponent());
|
||||||
|
ko.components.register("save-query-pane", new PaneComponents.SaveQueryPaneComponent());
|
||||||
|
ko.components.register("browse-queries-pane", new PaneComponents.BrowseQueriesPaneComponent());
|
||||||
|
ko.components.register("string-input-pane", new PaneComponents.StringInputPaneComponent());
|
||||||
|
ko.components.register("setup-notebooks-pane", new PaneComponents.SetupNotebooksPaneComponent());
|
||||||
|
ko.components.register("github-repos-pane", new PaneComponents.GitHubReposPaneComponent());
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import DeleteTriggerIcon from "../../images/DeleteTrigger.svg";
|
|||||||
import DeleteUDFIcon from "../../images/DeleteUDF.svg";
|
import DeleteUDFIcon from "../../images/DeleteUDF.svg";
|
||||||
import HostedTerminalIcon from "../../images/Hosted-Terminal.svg";
|
import HostedTerminalIcon from "../../images/Hosted-Terminal.svg";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
import { TreeNodeMenuItem } from "./Controls/TreeComponent/TreeComponent";
|
import { TreeNodeMenuItem } from "./Controls/TreeComponent/TreeComponent";
|
||||||
import Explorer from "./Explorer";
|
import Explorer from "./Explorer";
|
||||||
@@ -29,16 +30,16 @@ export interface DatabaseContextMenuButtonParams {
|
|||||||
* New resource tree (in ReactJS)
|
* New resource tree (in ReactJS)
|
||||||
*/
|
*/
|
||||||
export class ResourceTreeContextMenuButtonFactory {
|
export class ResourceTreeContextMenuButtonFactory {
|
||||||
public static createDatabaseContextMenu(container: Explorer, databaseId: string): TreeNodeMenuItem[] {
|
public static createDatabaseContextMenu(container: Explorer): TreeNodeMenuItem[] {
|
||||||
const items: TreeNodeMenuItem[] = [
|
const items: TreeNodeMenuItem[] = [
|
||||||
{
|
{
|
||||||
iconSrc: AddCollectionIcon,
|
iconSrc: AddCollectionIcon,
|
||||||
onClick: () => container.onNewCollectionClicked(databaseId),
|
onClick: () => container.onNewCollectionClicked(),
|
||||||
label: container.addCollectionText(),
|
label: container.addCollectionText(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (userContext.apiType !== "Tables") {
|
if (userContext.defaultExperience !== DefaultAccountExperienceType.Table) {
|
||||||
items.push({
|
items.push({
|
||||||
iconSrc: DeleteDatabaseIcon,
|
iconSrc: DeleteDatabaseIcon,
|
||||||
onClick: () => container.openDeleteDatabaseConfirmationPane(),
|
onClick: () => container.openDeleteDatabaseConfirmationPane(),
|
||||||
@@ -54,7 +55,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
selectedCollection: ViewModels.Collection
|
selectedCollection: ViewModels.Collection
|
||||||
): TreeNodeMenuItem[] {
|
): TreeNodeMenuItem[] {
|
||||||
const items: TreeNodeMenuItem[] = [];
|
const items: TreeNodeMenuItem[] = [];
|
||||||
if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") {
|
if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) {
|
||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddSqlQueryIcon,
|
iconSrc: AddSqlQueryIcon,
|
||||||
onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null),
|
onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null),
|
||||||
@@ -62,7 +63,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userContext.apiType === "Mongo") {
|
if (container.isPreferredApiMongoDB()) {
|
||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddSqlQueryIcon,
|
iconSrc: AddSqlQueryIcon,
|
||||||
onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, null),
|
onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, null),
|
||||||
@@ -79,7 +80,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") {
|
if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) {
|
||||||
items.push({
|
items.push({
|
||||||
iconSrc: AddStoredProcedureIcon,
|
iconSrc: AddStoredProcedureIcon,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@@ -122,7 +123,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
container: Explorer,
|
container: Explorer,
|
||||||
storedProcedure: StoredProcedure
|
storedProcedure: StoredProcedure
|
||||||
): TreeNodeMenuItem[] {
|
): TreeNodeMenuItem[] {
|
||||||
if (userContext.apiType === "Cassandra") {
|
if (container.isPreferredApiCassandra()) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static createTriggerContextMenuItems(container: Explorer, trigger: Trigger): TreeNodeMenuItem[] {
|
public static createTriggerContextMenuItems(container: Explorer, trigger: Trigger): TreeNodeMenuItem[] {
|
||||||
if (userContext.apiType === "Cassandra") {
|
if (container.isPreferredApiCassandra()) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +154,7 @@ export class ResourceTreeContextMenuButtonFactory {
|
|||||||
container: Explorer,
|
container: Explorer,
|
||||||
userDefinedFunction: UserDefinedFunction
|
userDefinedFunction: UserDefinedFunction
|
||||||
): TreeNodeMenuItem[] {
|
): TreeNodeMenuItem[] {
|
||||||
if (userContext.apiType === "Cassandra") {
|
if (container.isPreferredApiCassandra()) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class AccessibleElement extends React.Component<AccessibleElementProps> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
const elementProps = { ...this.props };
|
const elementProps = { ...this.props };
|
||||||
delete elementProps.as;
|
delete elementProps.as;
|
||||||
delete elementProps.onActivated;
|
delete elementProps.onActivated;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import TriangleRightIcon from "../../../../images/Triangle-right.svg";
|
|||||||
export interface AccordionComponentProps {}
|
export interface AccordionComponentProps {}
|
||||||
|
|
||||||
export class AccordionComponent extends React.Component<AccordionComponentProps> {
|
export class AccordionComponent extends React.Component<AccordionComponentProps> {
|
||||||
public override render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return <div className="accordion">{this.props.children}</div>;
|
return <div className="accordion">{this.props.children}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ export class AccordionItemComponent extends React.Component<AccordionItemCompone
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
if (this.props.isExpanded !== this.isExpanded) {
|
if (this.props.isExpanded !== this.isExpanded) {
|
||||||
this.isExpanded = this.props.isExpanded;
|
this.isExpanded = this.props.isExpanded;
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -51,7 +51,7 @@ public override componentDidUpdate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="accordionItemContainer">
|
<div className="accordionItemContainer">
|
||||||
<div className="accordionItemHeader" onClick={this.onHeaderClick} onKeyPress={this.onHeaderKeyPress}>
|
<div className="accordionItemHeader" onClick={this.onHeaderClick} onKeyPress={this.onHeaderKeyPress}>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { DefaultButton, IButtonStyles, IContextualMenuItem, IContextualMenuProps } from "@fluentui/react";
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
|
||||||
import * as Logger from "../../../Common/Logger";
|
|
||||||
import { ArcadiaWorkspace, SparkPool } from "../../../Contracts/DataModels";
|
import { ArcadiaWorkspace, SparkPool } from "../../../Contracts/DataModels";
|
||||||
|
import { DefaultButton, IButtonStyles } from "office-ui-fabric-react/lib/Button";
|
||||||
|
import { IContextualMenuItem, IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu";
|
||||||
|
import * as Logger from "../../../Common/Logger";
|
||||||
|
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
||||||
|
|
||||||
export interface ArcadiaMenuPickerProps {
|
export interface ArcadiaMenuPickerProps {
|
||||||
selectText?: string;
|
selectText?: string;
|
||||||
@@ -62,7 +63,7 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
|
|||||||
this.props.onCreateNewSparkPoolClicked(item.key);
|
this.props.onCreateNewSparkPoolClicked(item.key);
|
||||||
};
|
};
|
||||||
|
|
||||||
public override render() {
|
public render() {
|
||||||
const { workspaces } = this.props;
|
const { workspaces } = this.props;
|
||||||
let workspaceMenuItems: IContextualMenuItem[] = workspaces.map((workspace) => {
|
let workspaceMenuItems: IContextualMenuItem[] = workspaces.map((workspace) => {
|
||||||
let sparkPoolsMenuProps: IContextualMenuProps = {
|
let sparkPoolsMenuProps: IContextualMenuProps = {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export interface CollapsiblePanelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class CollapsiblePanel extends React.Component<CollapsiblePanelProps> {
|
export class CollapsiblePanel extends React.Component<CollapsiblePanelProps> {
|
||||||
public override render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className={`collapsiblePanel ${this.props.isCollapsed ? "paneCollapsed" : ""}`}>
|
<div className={`collapsiblePanel ${this.props.isCollapsed ? "paneCollapsed" : ""}`}>
|
||||||
{!this.props.isCollapsed ? this.getExpandedFragment() : this.getCollapsedFragment()}
|
{!this.props.isCollapsed ? this.getExpandedFragment() : this.getCollapsedFragment()}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { Icon, Label, Stack } from "@fluentui/react";
|
import { Icon, Label, Stack } from "office-ui-fabric-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { accordionStackTokens } from "../Settings/SettingsRenderUtils";
|
import { accordionStackTokens } from "../Settings/SettingsRenderUtils";
|
||||||
|
|
||||||
export interface CollapsibleSectionProps {
|
export interface CollapsibleSectionProps {
|
||||||
title: string;
|
title: string;
|
||||||
isExpandedByDefault: boolean;
|
isExpandedByDefault: boolean;
|
||||||
onExpand?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CollapsibleSectionState {
|
export interface CollapsibleSectionState {
|
||||||
@@ -24,13 +23,7 @@ export class CollapsibleSectionComponent extends React.Component<CollapsibleSect
|
|||||||
this.setState({ isExpanded: !this.state.isExpanded });
|
this.setState({ isExpanded: !this.state.isExpanded });
|
||||||
};
|
};
|
||||||
|
|
||||||
public override componentDidUpdate(): void {
|
public render(): JSX.Element {
|
||||||
if (this.state.isExpanded && this.props.onExpand) {
|
|
||||||
this.props.onExpand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override render(): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack
|
<Stack
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user