diff --git a/.eslintignore b/.eslintignore index 4e26bfc06..94f7c3e83 100644 --- a/.eslintignore +++ b/.eslintignore @@ -90,8 +90,7 @@ src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.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.ts src/Explorer/Menus/ContextMenu.ts @@ -123,13 +122,11 @@ src/Explorer/Panes/ContextualPaneBase.ts src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts src/Explorer/Panes/GraphStylingPane.ts -src/Explorer/Panes/NewVertexPane.ts +# src/Explorer/Panes/NewVertexPane.ts src/Explorer/Panes/PaneComponents.ts src/Explorer/Panes/RenewAdHocAccessPane.ts -src/Explorer/Panes/SetupNotebooksPane.ts src/Explorer/Panes/StringInputPane.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/TableEntityPane.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c26bae620..76bb1325e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,8 @@ jobs: PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }} endtoendemulator: name: "End To End Emulator Tests" - if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/') + # Temporarily disabled. This test needs to be rewritten in playwright + if: false runs-on: windows-latest steps: - uses: actions/checkout@v2 @@ -126,58 +127,21 @@ jobs: with: name: screenshots path: failed-* - accessibility: - 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] + endtoend: + name: "E2E" runs-on: ubuntu-latest env: 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 }} - 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: fail-fast: false matrix: test-file: - ./test/cassandra/container.spec.ts - - ./test/mongo/mongoIndexPolicy.spec.ts - - ./test/notebooks/uploadAndOpenNotebook.spec.ts - - ./test/selfServe/selfServeExample.spec.ts - ./test/sql/container.spec.ts + - ./test/mongo/container.spec.ts + - ./test/selfServe/selfServeExample.spec.ts + - ./test/notebooks/upload.spec.ts - ./test/sql/resourceToken.spec.ts - ./test/tables/container.spec.ts steps: @@ -188,30 +152,17 @@ jobs: node-version: 14.x - run: npm ci - run: npm start & - - run: node utils/cleanupDBs.js - run: npm run wait-for-server - name: ${{ matrix['test-file'] }} - run: npx jest -c ./jest.config.e2e.js --detectOpenHandles ${{ matrix['test-file'] }} + run: | + # 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 - uses: actions/upload-artifact@v2 if: failure() with: name: 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 + path: screenshots/ nuget: name: Publish Nuget if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/') diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml new file mode 100644 index 000000000..d00fd9724 --- /dev/null +++ b/.github/workflows/cleanup.yml @@ -0,0 +1,28 @@ +# 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 diff --git a/.gitignore b/.gitignore index 109e6c4d2..be016240b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ Contracts/* .DS_Store .cache/ .env -failure.png \ No newline at end of file +failure.png +screenshots/* +GettingStarted-ignore*.ipynb \ No newline at end of file diff --git a/CODING_GUIDELINES.md b/CODING_GUIDELINES.md index daa14a470..bad2583ab 100644 --- a/CODING_GUIDELINES.md +++ b/CODING_GUIDELINES.md @@ -153,7 +153,7 @@ Cosmos Explorer has been under constant development for over 5 years. As a resul ✅ DO -- Use [Puppeteer](https://developers.google.com/web/tools/puppeteer) and [Jest](https://jestjs.io/) +- Use [Playwright](https://github.com/microsoft/playwright) and [Jest](https://jestjs.io/) - 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. diff --git a/externals/iframeResizer.contentWindow.min.js b/externals/iframeResizer.contentWindow.min.js new file mode 100644 index 000000000..f711ae4fe --- /dev/null +++ b/externals/iframeResizer.contentWindow.min.js @@ -0,0 +1,10 @@ +/*! iFrame Resizer (iframeSizer.contentWindow.min.js) - v4.3.1 - 2021-01-11 + * Desc: Include this file in any page being loaded into an iframe + * to force the iframe to resize to the content size. + * Requires: iframeResizer.min.js on host page. + * Copyright: (c) 2021 David J. Bradshaw - dave@bradshaw.net + * License: MIT + */ + +!function(u){if("undefined"!=typeof window){var n=!0,o=10,i="",r=0,a="",t=null,c="",s=!1,d={resize:1,click:1},l=128,f=!0,m=1,h="bodyOffset",g=h,p=!0,v="",y={},w=32,b=null,T=!1,E=!1,O="[iFrameSizer]",S=O.length,M="",I={max:1,min:1,bodyScroll:1,documentElementScroll:1},N="child",A=!0,C=window.parent,z="*",k=0,R=!1,e=null,x=16,L=1,F="scroll",P=F,D=window,j=function(){ae("onMessage function not defined")},q=function(){},H=function(){},W={height:function(){return ae("Custom height calculation function not defined"),document.documentElement.offsetHeight},width:function(){return ae("Custom width calculation function not defined"),document.body.scrollWidth}},B={},J=!1;try{var U=Object.create({},{passive:{get:function(){J=!0}}});window.addEventListener("test",te,U),window.removeEventListener("test",te,U)}catch(e){}var V,X,Y,K,Q,G,Z=Date.now||function(){return(new Date).getTime()},$={bodyOffset:function(){return document.body.offsetHeight+ve("marginTop")+ve("marginBottom")},offset:function(){return $.bodyOffset()},bodyScroll:function(){return document.body.scrollHeight},custom:function(){return W.height()},documentElementOffset:function(){return document.documentElement.offsetHeight},documentElementScroll:function(){return document.documentElement.scrollHeight},max:function(){return Math.max.apply(null,we($))},min:function(){return Math.min.apply(null,we($))},grow:function(){return $.max()},lowestElement:function(){return Math.max($.bodyOffset()||$.documentElementOffset(),ye("bottom",Te()))},taggedElement:function(){return be("bottom","data-iframe-height")}},_={bodyScroll:function(){return document.body.scrollWidth},bodyOffset:function(){return document.body.offsetWidth},custom:function(){return W.width()},documentElementScroll:function(){return document.documentElement.scrollWidth},documentElementOffset:function(){return document.documentElement.offsetWidth},scroll:function(){return Math.max(_.bodyScroll(),_.documentElementScroll())},max:function(){return Math.max.apply(null,we(_))},min:function(){return Math.min.apply(null,we(_))},rightMostElement:function(){return ye("right",Te())},taggedElement:function(){return be("right","data-iframe-width")}},ee=(V=Ee,Q=null,G=0,function(){var e=Z(),t=x-(e-(G=G||e));return X=this,Y=arguments,t<=0||x/test/**/*.spec.[jt]s?(x)"], - setupFiles: ["dotenv/config"], -}; diff --git a/jest.config.playwright.js b/jest.config.playwright.js new file mode 100644 index 000000000..c452a5368 --- /dev/null +++ b/jest.config.playwright.js @@ -0,0 +1,7 @@ +module.exports = { + preset: "jest-playwright-preset", + testMatch: ["/test/**/*.spec.[jt]s?(x)"], + setupFiles: ["dotenv/config"], + testEnvironment: "./test/playwrightEnv.js", + setupFilesAfterEnv: ["expect-playwright"], +}; diff --git a/package-lock.json b/package-lock.json index 74e9d525c..f15966df5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2183,57 +2183,18 @@ "tslib": "^1.10.0" } }, - "@hapi/address": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", - "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==", - "dev": true - }, - "@hapi/bourne": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", - "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==", - "dev": true - }, "@hapi/formula": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==", "dev": true }, - "@hapi/hoek": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", - "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", - "dev": true - }, - "@hapi/joi": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", - "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", - "dev": true, - "requires": { - "@hapi/address": "2.x.x", - "@hapi/bourne": "1.x.x", - "@hapi/hoek": "8.x.x", - "@hapi/topo": "3.x.x" - } - }, "@hapi/pinpoint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==", "dev": true }, - "@hapi/topo": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", - "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", - "dev": true, - "requires": { - "@hapi/hoek": "^8.3.0" - } - }, "@icons/material": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", @@ -4519,6 +4480,35 @@ "@phosphor/virtualdom": "^1.2.0" } }, + "@sideway/address": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.1.tgz", + "integrity": "sha512-+I5aaQr3m0OAmMr7RQ3fR9zx55sejEYR2BFJaxL+zT3VM2611X0SHvPWIbAUBZVTn/YzYKbV8gJ2oT/QELknfQ==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + }, + "dependencies": { + "@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==", + "dev": true + } + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -4528,6 +4518,15 @@ "type-detect": "4.0.8" } }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, "@sinonjs/formatio": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", @@ -5115,16 +5114,6 @@ "@types/enzyme": "*" } }, - "@types/expect-puppeteer": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@types/expect-puppeteer/-/expect-puppeteer-4.4.5.tgz", - "integrity": "sha512-vxPaumA8Fj6xlm3llKCR9V8L936HX4PyipaNMxDbWQIOWZoCl99jabD/6xuxXnCptOWUdUhXwDuX5cAJgCHsLg==", - "dev": true, - "requires": { - "@types/jest": "*", - "@types/puppeteer": "*" - } - }, "@types/geojson": { "version": "7946.0.7", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", @@ -5168,6 +5157,12 @@ "hoist-non-react-statics": "^3.3.0" } }, + "@types/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", + "dev": true + }, "@types/invariant": { "version": "2.2.34", "resolved": "https://registry.npmjs.org/@types/invariant/-/invariant-2.2.34.tgz", @@ -5324,17 +5319,6 @@ } } }, - "@types/jest-environment-puppeteer": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@types/jest-environment-puppeteer/-/jest-environment-puppeteer-4.4.1.tgz", - "integrity": "sha512-LiZTD6i63le6QMnxi7pJB0SFv/fWtss6VVEEDm/UaeowBgjduf8txyE//j3WEeDPxngTvioUjbzA7Rc6Wc3cBA==", - "dev": true, - "requires": { - "@jest/types": ">=24 <=26", - "@types/puppeteer": "*", - "jest-environment-node": ">=24 <=26" - } - }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -5404,6 +5388,12 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/post-robot": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/post-robot/-/post-robot-10.0.1.tgz", + "integrity": "sha512-1k27bJ7MfTScedBeK8m4hYFLaiBkB6PbMHiux0gW1gJDGaqU89YICxl5kHX3KT/Dz6k04RfncfR1XDfD3Kou2Q==", + "dev": true + }, "@types/prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.1.tgz", @@ -5421,15 +5411,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.8.tgz", "integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==" }, - "@types/puppeteer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-5.4.3.tgz", - "integrity": "sha512-3nE8YgR9DIsgttLW+eJf6mnXxq8Ge+27m5SU3knWmrlfl6+KOG0Bf9f7Ua7K+C4BnaTMAh3/UpySqdAYvrsvjg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", @@ -5635,6 +5616,12 @@ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==" }, + "@types/wait-on": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/wait-on/-/wait-on-5.2.0.tgz", + "integrity": "sha512-3+jsMyPm8aot1mqDUDLOl+dejPvpysUUoUXD6CCRY20MNNhcjEfvdcBnGdnk7DEYs9Hr16ubGJA/9/QW0Df/9g==", + "dev": true + }, "@types/webpack": { "version": "4.41.26", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz", @@ -6458,6 +6445,12 @@ } } }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "dev": true + }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -6602,6 +6595,15 @@ "normalize-path": "^2.1.1" } }, + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" + } + }, "applicationinsights": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.8.0.tgz", @@ -6915,21 +6917,6 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "axe-core": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz", - "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==", - "dev": true - }, - "axe-puppeteer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/axe-puppeteer/-/axe-puppeteer-1.1.0.tgz", - "integrity": "sha512-VS17Y1rDQe6A0PdeTPxwOSBfmOdj6efgxyre9cN1du1snnVilczSDtQsgifBKBlzoL/3DKfGpgIi+N+zrzODOg==", - "dev": true, - "requires": { - "axe-core": "^3.5.3" - } - }, "axios": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", @@ -7226,6 +7213,16 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==" }, + "belter": { + "version": "1.0.164", + "resolved": "https://registry.npmjs.org/belter/-/belter-1.0.164.tgz", + "integrity": "sha512-aDRwk/yvRmesbEXixhbJ0kGeFmJth2kXZtqB8Dpk5xpfU79VPu+AX5DkE3b4Q6wCINNIetYhSZdSE255IKao2g==", + "requires": { + "cross-domain-safe-weakmap": "^1", + "cross-domain-utils": "^2", + "zalgo-promise": "^1" + } + }, "bfj": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", @@ -7268,6 +7265,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "optional": true, "requires": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -7278,6 +7276,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "optional": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -7287,6 +7286,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -7714,6 +7714,47 @@ "unset-value": "^1.0.0" } }, + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "requires": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -7991,6 +8032,12 @@ "safe-buffer": "^5.0.1" } }, + "cjs-module-lexer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", + "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", + "dev": true + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -8119,39 +8166,6 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, - "clone-deep": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", - "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", - "dev": true, - "requires": { - "for-own": "^0.1.3", - "is-plain-object": "^2.0.1", - "kind-of": "^3.0.2", - "lazy-cache": "^1.0.3", - "shallow-clone": "^0.1.2" - }, - "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "cls-hooked": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", @@ -8590,6 +8604,22 @@ "warning": "^4.0.3" } }, + "cross-domain-safe-weakmap": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/cross-domain-safe-weakmap/-/cross-domain-safe-weakmap-1.0.28.tgz", + "integrity": "sha512-gfQiQYSdWr9cYFVpmzp+b6MyTnefefDHr+fvm+JVv20hQxetV5J6chZOAusrpM/kFpTTbVDnHCziBFaREvgc0Q==", + "requires": { + "cross-domain-utils": "^2.0.0" + } + }, + "cross-domain-utils": { + "version": "2.0.34", + "resolved": "https://registry.npmjs.org/cross-domain-utils/-/cross-domain-utils-2.0.34.tgz", + "integrity": "sha512-ke4PirGRXwEElEmE/7k5aCvCW+EqbgseT7AOObzFfaVnOLuEVN9SjVWoOfS/qAT0rDPn3ggmNDW6mguMBy4HgA==", + "requires": { + "zalgo-promise": "^1.0.11" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -9319,6 +9349,12 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "decimal.js": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", + "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -9333,6 +9369,12 @@ "mimic-response": "^2.0.0" } }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-diff": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", @@ -9392,6 +9434,23 @@ "ip-regex": "^2.1.0" } }, + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -9581,11 +9640,32 @@ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "dev": true }, - "devtools-protocol": { - "version": "0.0.854822", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.854822.tgz", - "integrity": "sha512-xd4D8kHQtB0KtWW0c9xBZD5LVtm9chkMOfs/3Yn01RhT/sFIsVtzTtypfKoFfWBaL+7xCYLxjOLkhwPXaX/Kcg==", - "dev": true + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } }, "diagnostic-channel": { "version": "0.3.1", @@ -9788,6 +9868,43 @@ } } }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, "dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", @@ -9883,6 +10000,12 @@ "shimmer": "^1.2.0" } }, + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", + "dev": true + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -10095,6 +10218,12 @@ "next-tick": "~1.0.0" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", @@ -10706,10 +10835,10 @@ "jest-regex-util": "^24.9.0" } }, - "expect-puppeteer": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-4.4.0.tgz", - "integrity": "sha512-6Ey4Xy2xvmuQu7z7YQtMsaMV0EHJRpVxIDOd5GRrm04/I3nkTKIutELfECsLp6le+b3SSa3cXhPiw6PgqzxYWA==", + "expect-playwright": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/expect-playwright/-/expect-playwright-0.3.3.tgz", + "integrity": "sha512-uoeyx2D5LawJdziMdweOp6cnZzFOOPT9VvPG6gOh6YC7N9pU0k2KpVlRiz/Vc/fFBiGUNNeJq2Aq+9GJ65Nfrw==", "dev": true }, "expose-loader": { @@ -11492,11 +11621,79 @@ "for-in": "^1.0.1" } }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, + "fork-ts-checker-webpack-plugin": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", + "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "chalk": "^2.4.1", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "semver": "^5.6.0", + "tapable": "^1.0.0", + "worker-rpc": "^0.1.0" + } + }, "form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", @@ -11556,10 +11753,17 @@ "readable-stream": "^2.0.0" } }, + "fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "optional": true }, "fs-exists-sync": { "version": "0.1.0", @@ -12160,6 +12364,24 @@ "minimalistic-assert": "^1.0.1" } }, + "hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + } + } + }, "hasher": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hasher/-/hasher-1.2.0.tgz", @@ -12274,6 +12496,15 @@ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" }, + "html-inline-css-webpack-plugin": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/html-inline-css-webpack-plugin/-/html-inline-css-webpack-plugin-1.11.0.tgz", + "integrity": "sha512-VOBX7DOSKTZGwJnToWYhfzq9tt3mbTV0VncCy3APA4ljME20NbkQYiixJMZu782Crpp/kEcml1HbZbYtlXQzgQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, "html-loader": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", @@ -12319,6 +12550,55 @@ } } }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, "html-parse-stringify2": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz", @@ -12352,50 +12632,22 @@ } }, "html-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", - "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", + "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", "dev": true, "requires": { - "html-minifier": "^3.2.3", - "loader-utils": "^0.2.16", - "lodash": "^4.17.3", - "pretty-error": "^2.0.2", - "tapable": "^1.0.0", - "toposort": "^1.0.0", + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", "util.promisify": "1.0.0" }, "dependencies": { - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", @@ -12612,6 +12864,20 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "iframe-resizer": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.1.tgz", + "integrity": "sha512-PkoTPNF6EYhTbDjogdKu7JVgKqRwwNBXMeywZaQyzEYM3BNltA8O9fIIrtUkmj+8VZGckXpwtXsWsaQ5lrhd0w==" + }, + "iframe-resizer-react": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iframe-resizer-react/-/iframe-resizer-react-1.1.0.tgz", + "integrity": "sha512-FrytSq91AIJaDgE+6uK/Vdd6IR8CrwLoZ6eGmL2qQMPTzF0xlSV2jaSzRRUh5V2fttD7vzl21jvBl97bV40eBw==", + "requires": { + "iframe-resizer": "^4.3.0", + "warning": "^4.0.3" + } + }, "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", @@ -12624,6 +12890,12 @@ "dev": true, "optional": true }, + "immer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", + "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==", + "dev": true + }, "immutable": { "version": "4.0.0-rc.12", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", @@ -13007,6 +13279,12 @@ "isobject": "^3.0.1" } }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "is-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", @@ -13023,6 +13301,12 @@ "is-unc-path": "^1.0.0" } }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -13118,6 +13402,15 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" }, + "istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "requires": { + "append-transform": "^2.0.0" + } + }, "istanbul-lib-instrument": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", @@ -13139,6 +13432,94 @@ } } }, + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "istanbul-lib-report": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", @@ -13399,18 +13780,18 @@ "dev": true }, "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.11.0" + "type-fest": "^0.21.3" }, "dependencies": { "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true } } @@ -13431,9 +13812,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -14600,6 +14981,1263 @@ "throat": "^4.0.0" } }, + "jest-circus": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-26.6.3.tgz", + "integrity": "sha512-ACrpWZGcQMpbv13XbzRzpytEJlilP/Su0JtNCi5r/xLpOUhnaIJr8leYYpLEMgPFURZISEHrnnpmB54Q/UziPw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "stack-utils": "^2.0.2", + "throat": "^5.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" + } + }, + "@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + } + }, + "@jest/globals": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" + } + }, + "@jest/source-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", + "dev": true, + "requires": { + "@jest/test-result": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" + } + }, + "@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/prettier": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.3.tgz", + "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "dev": true + }, + "@types/yargs": { + "version": "15.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", + "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "acorn": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz", + "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "babel-jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", + "dev": true, + "requires": { + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, + "jest-config": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.6.3", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2" + } + }, + "jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" + } + }, + "jest-environment-jsdom": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" + } + }, + "jest-environment-node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + } + }, + "jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true + }, + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" + } + }, + "jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", + "dev": true, + "requires": { + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true + }, + "jest-resolve": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" + } + }, + "jest-runner": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.7.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + } + }, + "jest-runtime": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^0.6.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.4.1" + } + }, + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "jsdom": { + "version": "16.5.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz", + "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.1.0", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "html-encoding-sniffer": "^2.0.1", + "is-potential-custom-element-name": "^1.0.0", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "request": "^2.88.2", + "request-promise-native": "^1.0.9", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.4", + "xml-name-validator": "^3.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", + "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", + "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.0.2", + "webidl-conversions": "^6.1.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + } + } + }, "jest-config": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", @@ -14648,85 +16286,6 @@ } } }, - "jest-dev-server": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-4.4.0.tgz", - "integrity": "sha512-STEHJ3iPSC8HbrQ3TME0ozGX2KT28lbT4XopPxUm2WimsX3fcB3YOptRh12YphQisMhfqNSNTZUmWyT3HEXS2A==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "cwd": "^0.10.0", - "find-process": "^1.4.3", - "prompts": "^2.3.0", - "spawnd": "^4.4.0", - "tree-kill": "^1.2.2", - "wait-on": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wait-on": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.3.0.tgz", - "integrity": "sha512-97dEuUapx4+Y12aknWZn7D25kkjMk16PbWoYzpSdA8bYpVfS6hpl2a2pOWZ3c+Tyt3/i4/pglyZctG3J4V1hWQ==", - "dev": true, - "requires": { - "@hapi/joi": "^15.0.3", - "core-js": "^2.6.5", - "minimist": "^1.2.0", - "request": "^2.88.0", - "rx": "^4.1.0" - } - } - } - }, "jest-diff": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", @@ -14783,69 +16342,6 @@ "jest-util": "^24.9.0" } }, - "jest-environment-puppeteer": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-4.4.0.tgz", - "integrity": "sha512-iV8S8+6qkdTM6OBR/M9gKywEk8GDSOe05hspCs5D8qKSwtmlUfdtHfB4cakdc68lC6YfK3AUsLirpfgodCHjzQ==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "cwd": "^0.10.0", - "jest-dev-server": "^4.4.0", - "merge-deep": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "jest-get-type": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", @@ -14936,19 +16432,1384 @@ "@jest/types": "^24.9.0" } }, + "jest-playwright-preset": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/jest-playwright-preset/-/jest-playwright-preset-1.5.1.tgz", + "integrity": "sha512-zsFAe61V72vSLkd1fCcf7YbHmbdAB82SLBdUuCUF43aODIojshQEDF88KdWL9P+4JQ+DvEABT+6sFX4sY0rR2w==", + "dev": true, + "requires": { + "expect-playwright": "^0.3.3", + "jest-circus": "^26.6.3", + "jest-environment-node": "^26.6.2", + "jest-process-manager": "^0.2.9", + "jest-runner": "^26.6.3", + "nyc": "^15.1.0", + "playwright-core": ">=1.2.0", + "rimraf": "^3.0.2", + "uuid": "^8.3.2" + }, + "dependencies": { + "@jest/console": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" + } + }, + "@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + } + }, + "@jest/globals": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" + } + }, + "@jest/source-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", + "dev": true, + "requires": { + "@jest/test-result": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" + } + }, + "@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/prettier": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.3.tgz", + "integrity": "sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "dev": true + }, + "@types/yargs": { + "version": "15.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", + "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "acorn": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.1.1.tgz", + "integrity": "sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "babel-jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", + "dev": true, + "requires": { + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", + "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^4.0.0", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, + "jest-config": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.6.3", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2" + } + }, + "jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" + } + }, + "jest-environment-jsdom": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" + } + }, + "jest-environment-node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + } + }, + "jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true + }, + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" + } + }, + "jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", + "dev": true, + "requires": { + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true + }, + "jest-resolve": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" + } + }, + "jest-runner": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.7.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + } + }, + "jest-runtime": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^0.6.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.4.1" + } + }, + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "jsdom": { + "version": "16.5.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.3.tgz", + "integrity": "sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.1.0", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "html-encoding-sniffer": "^2.0.1", + "is-potential-custom-element-name": "^1.0.0", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "request": "^2.88.2", + "request-promise-native": "^1.0.9", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.4", + "xml-name-validator": "^3.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "playwright-core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.10.0.tgz", + "integrity": "sha512-SDA5KPwnJJSfnNX/b7h8y0ChwBmcbbcCofYXkZGMVuzXZsmHPGLOBRhgkwN2nzJ10Ezf4cd1OcVOeOLKPxjeRg==", + "dev": true, + "requires": { + "commander": "^6.1.0", + "debug": "^4.1.1", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "jpeg-js": "^0.4.2", + "mime": "^2.4.6", + "pngjs": "^5.0.0", + "progress": "^2.0.3", + "proper-lockfile": "^4.1.1", + "proxy-from-env": "^1.1.0", + "rimraf": "^3.0.2", + "stack-utils": "^2.0.3", + "ws": "^7.3.1" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", + "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz", + "integrity": "sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.0.2", + "webidl-conversions": "^6.1.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + } + } + }, "jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" }, - "jest-puppeteer": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-4.4.0.tgz", - "integrity": "sha512-ZaiCTlPZ07B9HW0erAWNX6cyzBqbXMM7d2ugai4epBDKpKvRDpItlRQC6XjERoJELKZsPziFGS0OhhUvTvQAXA==", + "jest-process-manager": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/jest-process-manager/-/jest-process-manager-0.2.9.tgz", + "integrity": "sha512-IKVdOSz1NLwKg9HTeyEDn63waMvKK6wcS+tCarGquNIktlXt4zAW2cfJ9vAA/xBcidWYKOPXHvy1l1N8qfw3Ww==", "dev": true, "requires": { - "expect-puppeteer": "^4.4.0", - "jest-environment-puppeteer": "^4.4.0" + "@types/wait-on": "^5.2.0", + "chalk": "^4.1.0", + "cwd": "^0.10.0", + "exit": "^0.1.2", + "find-process": "^1.4.4", + "prompts": "^2.4.0", + "signal-exit": "^3.0.3", + "spawnd": "^4.4.0", + "tree-kill": "^1.2.2", + "wait-on": "^5.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wait-on": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz", + "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==", + "dev": true, + "requires": { + "axios": "^0.21.1", + "joi": "^17.3.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^6.6.3" + } + } } }, "jest-regex-util": { @@ -15178,6 +18039,42 @@ } } }, + "joi": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", + "integrity": "sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + }, + "dependencies": { + "@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==", + "dev": true + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + } + } + }, + "jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", + "dev": true + }, "jquery": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", @@ -15467,12 +18364,6 @@ "resolved": "https://registry.npmjs.org/labella/-/labella-1.1.4.tgz", "integrity": "sha1-xsxaNA6N80DrM1YzaD6lm4KMMi0=" }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -16027,28 +18918,6 @@ "is-what": "^3.3.1" } }, - "merge-deep": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", - "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "clone-deep": "^0.2.4", - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -16071,6 +18940,12 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, + "microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", + "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -16272,24 +19147,6 @@ } } }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } - } - }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -16298,7 +19155,8 @@ "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "optional": true }, "moment": { "version": "2.29.1", @@ -16593,6 +19451,15 @@ "requires": { "inherits": "2.0.3" } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -16620,6 +19487,15 @@ } } }, + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, "node-releases": { "version": "1.1.70", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", @@ -16708,6 +19584,302 @@ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" }, + "nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "requires": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -17171,6 +20343,15 @@ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -17216,6 +20397,18 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -17356,6 +20549,43 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -17509,6 +20739,68 @@ "find-up": "^3.0.0" } }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "playwright": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.10.0.tgz", + "integrity": "sha512-b7SGBcCPq4W3pb4ImEDmNXtO0ZkJbZMuWiShsaNJd+rGfY/6fqwgllsAojmxGSgFmijYw7WxCoPiAIEDIH16Kw==", + "dev": true, + "requires": { + "commander": "^6.1.0", + "debug": "^4.1.1", + "extract-zip": "^2.0.1", + "https-proxy-agent": "^5.0.0", + "jpeg-js": "^0.4.2", + "mime": "^2.4.6", + "pngjs": "^5.0.0", + "progress": "^2.0.3", + "proper-lockfile": "^4.1.1", + "proxy-from-env": "^1.1.0", + "rimraf": "^3.0.2", + "stack-utils": "^2.0.3", + "ws": "^7.3.1" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + } + } + }, "plotly.js-cartesian-dist-min": { "version": "1.52.3", "resolved": "https://registry.npmjs.org/plotly.js-cartesian-dist-min/-/plotly.js-cartesian-dist-min-1.52.3.tgz", @@ -17524,6 +20816,12 @@ "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true + }, "polygon-offset": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/polygon-offset/-/polygon-offset-0.3.1.tgz", @@ -17573,6 +20871,18 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, + "post-robot": { + "version": "10.0.42", + "resolved": "https://registry.npmjs.org/post-robot/-/post-robot-10.0.42.tgz", + "integrity": "sha512-fuIuJblIbiAUJVKvttYZ1ZABhvrtAJgxZZ/TsWzzAdQGzkXOaewwgvFiGOSZRr0DywRaQs0Wvgxa7bFCYh8pfg==", + "requires": { + "belter": "^1.0.41", + "cross-domain-safe-weakmap": "^1.0.1", + "cross-domain-utils": "^2.0.0", + "universal-serialize": "^1.0.4", + "zalgo-promise": "^1.0.3" + } + }, "postcss": { "version": "8.2.10", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.10.tgz", @@ -17822,6 +21132,15 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -17873,6 +21192,17 @@ "reflect.ownkeys": "^0.2.0" } }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "property-information": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", @@ -17959,91 +21289,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "puppeteer": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-8.0.0.tgz", - "integrity": "sha512-D0RzSWlepeWkxPPdK3xhTcefj8rjah1791GE82Pdjsri49sy11ci/JQsAO8K2NRukqvwEtcI+ImP5F4ZiMvtIQ==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "devtools-protocol": "0.0.854822", - "extract-zip": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.1", - "pkg-dir": "^4.2.0", - "progress": "^2.0.1", - "proxy-from-env": "^1.1.0", - "rimraf": "^3.0.2", - "tar-fs": "^2.0.0", - "unbzip2-stream": "^1.3.3", - "ws": "^7.2.3" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "pure-color": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz", @@ -18208,6 +21453,225 @@ "tinycolor2": "^1.4.1" } }, + "react-dev-utils": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", + "integrity": "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==", + "dev": true, + "requires": { + "@babel/code-frame": "7.10.4", + "address": "1.1.2", + "browserslist": "4.14.2", + "chalk": "2.4.2", + "cross-spawn": "7.0.3", + "detect-port-alt": "1.1.6", + "escape-string-regexp": "2.0.0", + "filesize": "6.1.0", + "find-up": "4.1.0", + "fork-ts-checker-webpack-plugin": "4.1.6", + "global-modules": "2.0.0", + "globby": "11.0.1", + "gzip-size": "5.1.1", + "immer": "8.0.1", + "is-root": "2.1.0", + "loader-utils": "2.0.0", + "open": "^7.0.2", + "pkg-up": "3.1.0", + "prompts": "2.4.0", + "react-error-overlay": "^6.0.9", + "recursive-readdir": "2.2.2", + "shell-quote": "1.7.2", + "strip-ansi": "6.0.0", + "text-table": "0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "browserslist": { + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", + "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001125", + "electron-to-chromium": "^1.3.564", + "escalade": "^3.0.2", + "node-releases": "^1.1.61" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "filesize": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", + "integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "react-dnd": { "version": "9.4.0", "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-9.4.0.tgz", @@ -18250,6 +21714,12 @@ } } }, + "react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, "react-hot-loader": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.13.0.tgz", @@ -18534,6 +22004,15 @@ "resolve": "^1.1.6" } }, + "recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, "redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -18702,6 +22181,15 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, "remark-parse": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", @@ -18771,9 +22259,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", - "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", "dev": true } } @@ -19083,12 +22571,6 @@ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", - "dev": true - }, "rx-jupyter": { "version": "5.5.12", "resolved": "https://registry.npmjs.org/rx-jupyter/-/rx-jupyter-5.5.12.tgz", @@ -19526,35 +23008,6 @@ "safe-buffer": "^5.0.1" } }, - "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^2.0.1", - "lazy-cache": "^0.2.3", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "dev": true, - "requires": { - "is-buffer": "^1.0.2" - } - }, - "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", - "dev": true - } - } - }, "shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -19573,6 +23026,12 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -19888,6 +23347,46 @@ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" }, + "spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "requires": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "spawnd": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-4.4.0.tgz", @@ -19999,9 +23498,9 @@ } }, "ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "requires": { "minipass": "^3.1.1" } @@ -20437,6 +23936,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "optional": true, "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -20448,6 +23948,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "optional": true, "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -20460,6 +23961,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -20479,18 +23981,18 @@ }, "dependencies": { "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.11.0" + "type-fest": "^0.21.3" } }, "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true } } @@ -20708,12 +24210,6 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, - "toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, "tough-cookie": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", @@ -21006,9 +24502,9 @@ } }, "typescript": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", - "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true }, "typestyle": { @@ -21049,28 +24545,6 @@ "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=" }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -21204,6 +24678,11 @@ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz", "integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==" }, + "universal-serialize": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/universal-serialize/-/universal-serialize-1.0.8.tgz", + "integrity": "sha512-AhC3D26asmMkxAadYjCUJh98AUV/Fpp9uStVz4OuigpaGqIwY+i95EWE392P+4ObOPFHw8TUk/GazyiSGDtxhA==" + }, "universal-user-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", @@ -21886,9 +25365,9 @@ "dev": true }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", "dev": true, "requires": { "figgy-pudding": "^3.5.1" @@ -22474,6 +25953,15 @@ "errno": "~0.1.7" } }, + "worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", + "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "dev": true, + "requires": { + "microevent.ts": "~0.1.1" + } + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -22697,6 +26185,11 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zalgo-promise": { + "version": "1.0.46", + "resolved": "https://registry.npmjs.org/zalgo-promise/-/zalgo-promise-1.0.46.tgz", + "integrity": "sha512-tzPpQRqaQQavxl17TY98nznvmr+judUg3My7ugsUcRDbdqisYOE2z79HNNDgXnyX3eA0mf2bMOJrqHptt00npg==" } } } diff --git a/package.json b/package.json index 6191b9430..6e8587e42 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "i18next": "19.8.4", "i18next-browser-languagedetector": "6.0.1", "i18next-http-backend": "1.0.23", + "iframe-resizer-react": "1.1.0", "immutable": "4.0.0-rc.12", "is-ci": "2.0.0", "jquery": "3.5.1", @@ -78,6 +79,7 @@ "office-ui-fabric-react": "7.164.2", "p-retry": "4.2.0", "plotly.js-cartesian-dist-min": "1.52.3", + "post-robot": "10.0.42", "q": "1.5.1", "react": "16.13.1", "react-animate-height": "2.0.8", @@ -111,15 +113,12 @@ "@types/d3": "5.9.2", "@types/enzyme": "3.10.7", "@types/enzyme-adapter-react-16": "1.0.6", - "@types/expect-puppeteer": "4.4.5", "@types/hasher": "0.0.31", "@types/jest": "26.0.20", - "@types/jest-environment-puppeteer": "4.4.1", "@types/memoize-one": "4.1.1", "@types/node": "12.11.1", + "@types/post-robot": "10.0.1", "@types/promise.prototype.finally": "2.0.3", - "@types/prop-types": "15.5.8", - "@types/puppeteer": "5.4.3", "@types/q": "1.5.1", "@types/react": "17.0.3", "@types/react-dom": "17.0.3", @@ -131,7 +130,6 @@ "@types/underscore": "1.7.36", "@typescript-eslint/eslint-plugin": "4.0.1", "@typescript-eslint/parser": "4.0.1", - "axe-puppeteer": "1.1.0", "babel-jest": "24.9.0", "babel-loader": "8.1.0", "buffer": "5.1.0", @@ -146,16 +144,18 @@ "eslint-plugin-no-null": "1.0.2", "eslint-plugin-prefer-arrow": "1.2.2", "eslint-plugin-react-hooks": "4.2.0", + "expect-playwright": "0.3.3", "expose-loader": "0.7.5", "fast-glob": "3.2.5", "file-loader": "2.0.0", "fs-extra": "7.0.0", + "html-inline-css-webpack-plugin": "1.11.0", "html-loader": "0.5.5", "html-loader-jest": "0.2.1", - "html-webpack-plugin": "3.2.0", + "html-webpack-plugin": "4.5.2", "jest": "25.5.4", "jest-canvas-mock": "2.1.0", - "jest-puppeteer": "4.4.0", + "jest-playwright-preset": "1.5.1", "jest-trx-results-processor": "0.0.7", "less": "3.8.1", "less-loader": "4.1.0", @@ -163,16 +163,17 @@ "mini-css-extract-plugin": "0.4.3", "monaco-editor-webpack-plugin": "1.7.0", "node-fetch": "2.6.1", + "playwright": "1.10.0", "prettier": "2.2.1", - "puppeteer": "8.0.0", "raw-loader": "0.5.1", + "react-dev-utils": "11.0.4", "rimraf": "3.0.0", "sinon": "3.2.1", "style-loader": "0.23.0", "ts-loader": "6.2.2", "tslint": "5.11.0", "tslint-microsoft-contrib": "6.0.0", - "typescript": "4.2.3", + "typescript": "4.2.4", "url-loader": "1.1.1", "wait-on": "4.0.2", "webpack": "4.43.0", diff --git a/preview/index.js b/preview/index.js index 319d1079f..c17eec9ee 100644 --- a/preview/index.js +++ b/preview/index.js @@ -57,8 +57,6 @@ app.get("/pull/:pr(\\d+)", (req, res) => { const portal = new URL("https://ms.portal.azure.com/"); portal.searchParams.set("dataExplorerSource", explorer.href); - portal.hash = - "@microsoft.onmicrosoft.com/resource/subscriptions/b9c77f10-b438-4c32-9819-eef8a654e478/resourceGroups/stfaul/providers/Microsoft.DocumentDb/databaseAccounts/stfaul-sql/dataExplorer"; return res.redirect(portal.href); }) diff --git a/src/CellOutputViewer/CellOutputViewer.tsx b/src/CellOutputViewer/CellOutputViewer.tsx new file mode 100644 index 000000000..d5b8eb933 --- /dev/null +++ b/src/CellOutputViewer/CellOutputViewer.tsx @@ -0,0 +1,68 @@ +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 { TransformMedia } from "./TransformMedia"; + +export interface CellOutputViewerProps { + id: string; + contentRef: ContentRef; + hidden: boolean; + expanded: boolean; + 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 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const props = (event as any).data as CellOutputViewerProps; + const outputs = ( +
+ {props.outputs?.map((output, index) => ( + + props.onMetadataChange(metadata, mediaType, index)} + /> + props.onMetadataChange(metadata, mediaType, index)} + /> + + + + ))} +
+ ); + + ReactDOM.render(outputs, document.getElementById("cellOutput")); + } + ); +}; + +// Entry point +window.addEventListener("load", onInit); diff --git a/src/CellOutputViewer/TransformMedia.tsx b/src/CellOutputViewer/TransformMedia.tsx new file mode 100644 index 000000000..b38922042 --- /dev/null +++ b/src/CellOutputViewer/TransformMedia.tsx @@ -0,0 +1,138 @@ +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>([ + ["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 ( + Loading...}> + + + ); +}; + +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; diff --git a/src/CellOutputViewer/cellOutputViewer.html b/src/CellOutputViewer/cellOutputViewer.html new file mode 100644 index 000000000..7db8c5958 --- /dev/null +++ b/src/CellOutputViewer/cellOutputViewer.html @@ -0,0 +1,12 @@ + + + + + + Cell Output Viewer + + + +
+ + diff --git a/src/CellOutputViewer/transforms/Vega2.ts b/src/CellOutputViewer/transforms/Vega2.ts new file mode 100644 index 000000000..08a358f54 --- /dev/null +++ b/src/CellOutputViewer/transforms/Vega2.ts @@ -0,0 +1 @@ +export { Vega2 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/Vega3.ts b/src/CellOutputViewer/transforms/Vega3.ts new file mode 100644 index 000000000..87289b52f --- /dev/null +++ b/src/CellOutputViewer/transforms/Vega3.ts @@ -0,0 +1 @@ +export { Vega3 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/Vega4.ts b/src/CellOutputViewer/transforms/Vega4.ts new file mode 100644 index 000000000..a95100d63 --- /dev/null +++ b/src/CellOutputViewer/transforms/Vega4.ts @@ -0,0 +1 @@ +export { Vega4 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/Vega5.ts b/src/CellOutputViewer/transforms/Vega5.ts new file mode 100644 index 000000000..6fa20b452 --- /dev/null +++ b/src/CellOutputViewer/transforms/Vega5.ts @@ -0,0 +1 @@ +export { Vega5 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/VegaLite1.ts b/src/CellOutputViewer/transforms/VegaLite1.ts new file mode 100644 index 000000000..fb615d92c --- /dev/null +++ b/src/CellOutputViewer/transforms/VegaLite1.ts @@ -0,0 +1 @@ +export { VegaLite1 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/VegaLite2.ts b/src/CellOutputViewer/transforms/VegaLite2.ts new file mode 100644 index 000000000..f664e0bda --- /dev/null +++ b/src/CellOutputViewer/transforms/VegaLite2.ts @@ -0,0 +1 @@ +export { VegaLite2 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/VegaLite3.ts b/src/CellOutputViewer/transforms/VegaLite3.ts new file mode 100644 index 000000000..8a57abbc4 --- /dev/null +++ b/src/CellOutputViewer/transforms/VegaLite3.ts @@ -0,0 +1 @@ +export { VegaLite3 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/VegaLite4.ts b/src/CellOutputViewer/transforms/VegaLite4.ts new file mode 100644 index 000000000..fca92c80f --- /dev/null +++ b/src/CellOutputViewer/transforms/VegaLite4.ts @@ -0,0 +1 @@ +export { VegaLite4 as default } from "@nteract/transform-vega"; diff --git a/src/CellOutputViewer/transforms/WidgetDisplay.ts b/src/CellOutputViewer/transforms/WidgetDisplay.ts new file mode 100644 index 000000000..4387a4f5d --- /dev/null +++ b/src/CellOutputViewer/transforms/WidgetDisplay.ts @@ -0,0 +1 @@ +export { WidgetDisplay as default } from "@nteract/jupyter-widgets"; diff --git a/src/Common/EntityValue.tsx b/src/Common/EntityValue.tsx new file mode 100644 index 000000000..16d95a007 --- /dev/null +++ b/src/Common/EntityValue.tsx @@ -0,0 +1,61 @@ +import { DatePicker, TextField } from "office-ui-fabric-react"; +import React, { FunctionComponent } from "react"; + +export interface TableEntityProps { + entityValueLabel?: string; + entityValuePlaceholder: string; + entityValue: string | Date; + isEntityTypeDate: boolean; + entityTimeValue: string; + entityValueType: string; + onEntityValueChange: (event: React.FormEvent, newInput?: string) => void; + onSelectDate: (date: Date | null | undefined) => void; + onEntityTimeValueChange: (event: React.FormEvent, newInput?: string) => void; +} + +export const EntityValue: FunctionComponent = ({ + entityValueLabel, + entityValuePlaceholder, + entityValue, + isEntityTypeDate, + entityTimeValue, + entityValueType, + onEntityValueChange, + onSelectDate, + onEntityTimeValueChange, +}: TableEntityProps): JSX.Element => { + if (isEntityTypeDate) { + return ( + <> + + + + ); + } + + return ( + + ); +}; diff --git a/src/Common/MongoProxyClient.ts b/src/Common/MongoProxyClient.ts index 0680a26c2..ad22c9257 100644 --- a/src/Common/MongoProxyClient.ts +++ b/src/Common/MongoProxyClient.ts @@ -5,11 +5,10 @@ import { configContext } from "../ConfigContext"; import * as DataModels from "../Contracts/DataModels"; import { MessageTypes } from "../Contracts/ExplorerContracts"; import { Collection } from "../Contracts/ViewModels"; -import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import DocumentId from "../Explorer/Tree/DocumentId"; -import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils"; -import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants"; import { userContext } from "../UserContext"; +import { logConsoleError } from "../Utils/NotificationConsoleUtils"; +import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants"; import { MinimalQueryIterator } from "./IteratorUtilities"; import { sendMessage } from "./MessageHandler"; @@ -348,10 +347,7 @@ export function getEndpoint(): string { async function errorHandling(response: Response, action: string, params: unknown): Promise { const errorMessage = await response.text(); // Log the error where the user can see it - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error ${action}: ${errorMessage}, Payload: ${JSON.stringify(params)}` - ); + logConsoleError(`Error ${action}: ${errorMessage}, Payload: ${JSON.stringify(params)}`); if (response.status === HttpStatusCodes.Forbidden) { sendMessage({ type: MessageTypes.ForbiddenError, reason: errorMessage }); return; diff --git a/src/Common/TableEntity.tsx b/src/Common/TableEntity.tsx new file mode 100644 index 000000000..864929752 --- /dev/null +++ b/src/Common/TableEntity.tsx @@ -0,0 +1,136 @@ +import { + Dropdown, + IDropdownOption, + IDropdownStyles, + IImageProps, + Image, + IStackTokens, + Stack, + TextField, + TooltipHost, +} from "office-ui-fabric-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 = { 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; + onDeleteEntity?: () => void; + onEditEntity?: () => void; + onEntityPropertyChange: (event: React.FormEvent, newInput?: string) => void; + onEntityTypeChange: (event: React.FormEvent, selectedParam: IDropdownOption) => void; + onEntityValueChange: (event: React.FormEvent, newInput?: string) => void; + onSelectDate: (date: Date | null | undefined) => void; + onEntityTimeValueChange: (event: React.FormEvent, newInput?: string) => void; +} + +export const TableEntity: FunctionComponent = ({ + entityTypeLabel, + entityPropertyLabel, + isDeleteOptionVisible, + entityProperty, + selectedKey, + entityPropertyPlaceHolder, + entityValueLabel, + entityValuePlaceholder, + entityValue, + options, + isPropertyTypeDisable, + isEntityTypeDate, + entityTimeValue, + 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 ( + <> + + + + + + editEntity + + + {isDeleteOptionVisible && userContext.apiType !== "Cassandra" && ( + + delete entity + + )} + + + ); +}; diff --git a/src/Common/Tooltip/index.tsx b/src/Common/Tooltip/Tooltip.tsx similarity index 100% rename from src/Common/Tooltip/index.tsx rename to src/Common/Tooltip/Tooltip.tsx diff --git a/src/Common/Upload/index.tsx b/src/Common/Upload/Upload.tsx similarity index 95% rename from src/Common/Upload/index.tsx rename to src/Common/Upload/Upload.tsx index 6f0187bad..30cc6b51d 100644 --- a/src/Common/Upload/index.tsx +++ b/src/Common/Upload/Upload.tsx @@ -1,8 +1,8 @@ import { Image, Stack, TextField } from "office-ui-fabric-react"; import React, { ChangeEvent, FunctionComponent, KeyboardEvent, useRef, useState } from "react"; import FolderIcon from "../../../images/folder_16x16.svg"; -import * as Constants from "../../Common/Constants"; -import { Tooltip } from "../Tooltip"; +import * as Constants from "../Constants"; +import { Tooltip } from "../Tooltip/Tooltip"; interface UploadProps { label: string; diff --git a/src/Common/dataAccess/bulkCreateDocument.ts b/src/Common/dataAccess/bulkCreateDocument.ts index 0eb0d4475..ec7ae7b8f 100644 --- a/src/Common/dataAccess/bulkCreateDocument.ts +++ b/src/Common/dataAccess/bulkCreateDocument.ts @@ -22,9 +22,12 @@ export const bulkCreateDocument = async ( ); 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` + `${ + documents.length + } operations completed for container ${collection.id()}. ${successCount} operations succeeded. ${throttledCount} operations throttled` ); return response; } catch (error) { diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index 654928c6b..dc7d5f887 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -26,6 +26,7 @@ export interface ConfigContext { GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it. hostedExplorerURL: string; armAPIVersion?: string; + allowedJunoOrigins: string[]; } // Default configuration @@ -53,6 +54,13 @@ let configContext: Readonly = { GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306 JUNO_ENDPOINT: "https://tools.cosmos.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 { @@ -86,13 +94,18 @@ export async function initializeConfiguration(): Promise { }); if (response.status === 200) { try { - const { allowedParentFrameOrigins, ...externalConfig } = await response.json(); + const { allowedParentFrameOrigins, allowedJunoOrigins, ...externalConfig } = await response.json(); Object.assign(configContext, externalConfig); if (allowedParentFrameOrigins && allowedParentFrameOrigins.length > 0) { updateConfigContext({ allowedParentFrameOrigins: [...configContext.allowedParentFrameOrigins, ...allowedParentFrameOrigins], }); } + if (allowedJunoOrigins && allowedJunoOrigins.length > 0) { + updateConfigContext({ + allowedJunoOrigins: [...configContext.allowedJunoOrigins, ...allowedJunoOrigins], + }); + } } catch (error) { console.error("Unable to parse json in config file"); console.error(error); diff --git a/src/Contracts/ActionContracts.ts b/src/Contracts/ActionContracts.ts index dac45dbe0..f8fc956e6 100644 --- a/src/Contracts/ActionContracts.ts +++ b/src/Contracts/ActionContracts.ts @@ -4,6 +4,7 @@ export enum TabKind { SQLDocuments, MongoDocuments, + SchemaAnalyzer, TableEntities, Graph, SQLQuery, diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index 71d76624b..656b87eb8 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -141,6 +141,7 @@ export interface Collection extends CollectionBase { onTableEntitiesClick(): void; onGraphDocumentsClick(): void; onMongoDBDocumentsClick(): void; + onSchemaAnalyzerClick(): void; openTab(): void; onSettingsClick: () => Promise; @@ -276,7 +277,6 @@ export interface TabOptions { tabKind: CollectionTabKind; title: string; tabPath: string; - isActive: ko.Observable; hashLocation: string; onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void; isTabsContentExpanded?: ko.Observable; @@ -367,6 +367,7 @@ export enum CollectionTabKind { Schema = 19, CollectionSettingsV2 = 20, DatabaseSettingsV2 = 21, + SchemaAnalyzer = 22, } export enum TerminalKind { diff --git a/src/Explorer/ComponentRegisterer.test.ts b/src/Explorer/ComponentRegisterer.test.ts index 78e08fad1..98f5af729 100644 --- a/src/Explorer/ComponentRegisterer.test.ts +++ b/src/Explorer/ComponentRegisterer.test.ts @@ -8,10 +8,6 @@ describe("Component Registerer", () => { 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", () => { expect(ko.components.isRegistered("error-display")).toBe(true); }); @@ -73,10 +69,6 @@ describe("Component Registerer", () => { expect(ko.components.isRegistered("add-collection-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", () => { expect(ko.components.isRegistered("graph-styling-pane")).toBe(true); }); @@ -85,10 +77,6 @@ describe("Component Registerer", () => { 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", () => { expect(ko.components.isRegistered("dynamic-list")).toBe(true); }); diff --git a/src/Explorer/ComponentRegisterer.ts b/src/Explorer/ComponentRegisterer.ts index 7c8b84c1a..1f2984612 100644 --- a/src/Explorer/ComponentRegisterer.ts +++ b/src/Explorer/ComponentRegisterer.ts @@ -7,7 +7,6 @@ import { InputTypeaheadComponent } from "./Controls/InputTypeahead/InputTypeahea import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent"; import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3"; import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent"; -import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponent"; import * as PaneComponents from "./Panes/PaneComponents"; import ConflictsTab from "./Tabs/ConflictsTab"; import DocumentsTab from "./Tabs/DocumentsTab"; @@ -18,15 +17,14 @@ import NotebookTabV2 from "./Tabs/NotebookV2Tab"; import NotebookViewerTab from "./Tabs/NotebookViewerTab"; import QueryTab from "./Tabs/QueryTab"; import QueryTablesTab from "./Tabs/QueryTablesTab"; +import SchemaAnalyzerTab from "./Tabs/SchemaAnalyzerTab"; 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("new-vertex-form", NewVertexComponent); ko.components.register("error-display", new ErrorDisplayComponent()); ko.components.register("graph-style", GraphStyleComponent); ko.components.register("editor", new EditorComponent()); @@ -34,7 +32,6 @@ ko.components.register("json-editor", new JsonEditorComponent()); ko.components.register("diff-editor", new DiffEditorComponent()); ko.components.register("dynamic-list", DynamicListComponent); ko.components.register("throughput-input-autopilot-v3", ThroughputInputComponentAutoPilotV3); -ko.components.register("tabs-manager", { template: TabsManagerTemplate }); // Collection Tabs [ @@ -53,17 +50,15 @@ ko.components.register("tabs-manager", { template: TabsManagerTemplate }); GalleryTab, NotebookViewerTab, DatabaseSettingsTabV2, + SchemaAnalyzerTab, ].forEach(({ component: { name, template } }) => ko.components.register(name, { template })); // Panes ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent()); ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent()); - -ko.components.register("graph-new-vertex-pane", new PaneComponents.GraphNewVertexPaneComponent()); 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("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent()); 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()); diff --git a/src/Explorer/ContextMenuButtonFactory.ts b/src/Explorer/ContextMenuButtonFactory.ts index deb55ef5c..8337ec700 100644 --- a/src/Explorer/ContextMenuButtonFactory.ts +++ b/src/Explorer/ContextMenuButtonFactory.ts @@ -55,7 +55,7 @@ export class ResourceTreeContextMenuButtonFactory { selectedCollection: ViewModels.Collection ): TreeNodeMenuItem[] { const items: TreeNodeMenuItem[] = []; - if (userContext.apiType === "SQL" || container.isPreferredApiGraph()) { + if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") { items.push({ iconSrc: AddSqlQueryIcon, onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null), @@ -80,7 +80,7 @@ export class ResourceTreeContextMenuButtonFactory { }); } - if (userContext.apiType === "SQL" || container.isPreferredApiGraph()) { + if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") { items.push({ iconSrc: AddStoredProcedureIcon, onClick: () => { @@ -123,7 +123,7 @@ export class ResourceTreeContextMenuButtonFactory { container: Explorer, storedProcedure: StoredProcedure ): TreeNodeMenuItem[] { - if (container.isPreferredApiCassandra()) { + if (userContext.apiType === "Cassandra") { return []; } @@ -137,7 +137,7 @@ export class ResourceTreeContextMenuButtonFactory { } public static createTriggerContextMenuItems(container: Explorer, trigger: Trigger): TreeNodeMenuItem[] { - if (container.isPreferredApiCassandra()) { + if (userContext.apiType === "Cassandra") { return []; } @@ -154,7 +154,7 @@ export class ResourceTreeContextMenuButtonFactory { container: Explorer, userDefinedFunction: UserDefinedFunction ): TreeNodeMenuItem[] { - if (container.isPreferredApiCassandra()) { + if (userContext.apiType === "Cassandra") { return []; } diff --git a/src/Explorer/Controls/Dialog.tsx b/src/Explorer/Controls/Dialog.tsx index 3b69e45be..ffb19b31d 100644 --- a/src/Explorer/Controls/Dialog.tsx +++ b/src/Explorer/Controls/Dialog.tsx @@ -1,8 +1,3 @@ -import * as React from "react"; -import { Dialog as FluentDialog, DialogType, DialogFooter, IDialogProps } from "office-ui-fabric-react/lib/Dialog"; -import { IButtonProps, PrimaryButton, DefaultButton } from "office-ui-fabric-react/lib/Button"; -import { ITextFieldProps, TextField } from "office-ui-fabric-react/lib/TextField"; -import { Link } from "office-ui-fabric-react/lib/Link"; import { ChoiceGroup, FontIcon, @@ -10,6 +5,11 @@ import { IProgressIndicatorProps, ProgressIndicator, } from "office-ui-fabric-react"; +import { DefaultButton, IButtonProps, PrimaryButton } from "office-ui-fabric-react/lib/Button"; +import { Dialog as FluentDialog, DialogFooter, DialogType, IDialogProps } from "office-ui-fabric-react/lib/Dialog"; +import { Link } from "office-ui-fabric-react/lib/Link"; +import { ITextFieldProps, TextField } from "office-ui-fabric-react/lib/TextField"; +import React, { FunctionComponent } from "react"; export interface TextFieldProps extends ITextFieldProps { label: string; @@ -50,61 +50,69 @@ const DIALOG_TITLE_FONT_SIZE = "17px"; const DIALOG_TITLE_FONT_WEIGHT = 400; const DIALOG_SUBTEXT_FONT_SIZE = "15px"; -export class Dialog extends React.Component { - constructor(props: DialogProps) { - super(props); - } - - public render(): JSX.Element { - const dialogProps: IDialogProps = { - hidden: !this.props.visible, - dialogContentProps: { - type: this.props.type || DialogType.normal, - title: this.props.title, - subText: this.props.subText, - styles: { - title: { fontSize: DIALOG_TITLE_FONT_SIZE, fontWeight: DIALOG_TITLE_FONT_WEIGHT }, - subText: { fontSize: DIALOG_SUBTEXT_FONT_SIZE }, - }, - showCloseButton: this.props.showCloseButton || false, - onDismiss: this.props.onDismiss, +export const Dialog: FunctionComponent = ({ + title, + subText, + isModal, + visible, + choiceGroupProps, + textFieldProps, + linkProps, + progressIndicatorProps, + primaryButtonText, + secondaryButtonText, + onPrimaryButtonClick, + onSecondaryButtonClick, + primaryButtonDisabled, + type, + showCloseButton, + onDismiss, +}: DialogProps) => { + const dialogProps: IDialogProps = { + hidden: !visible, + dialogContentProps: { + type: type || DialogType.normal, + title, + subText, + styles: { + title: { fontSize: DIALOG_TITLE_FONT_SIZE, fontWeight: DIALOG_TITLE_FONT_WEIGHT }, + subText: { fontSize: DIALOG_SUBTEXT_FONT_SIZE }, }, - modalProps: { isBlocking: this.props.isModal, isDarkOverlay: false }, - minWidth: DIALOG_MIN_WIDTH, - maxWidth: DIALOG_MAX_WIDTH, - }; - const choiceGroupProps: IChoiceGroupProps = this.props.choiceGroupProps; - const textFieldProps: ITextFieldProps = this.props.textFieldProps; - const linkProps: LinkProps = this.props.linkProps; - const progressIndicatorProps: IProgressIndicatorProps = this.props.progressIndicatorProps; - const primaryButtonProps: IButtonProps = { - text: this.props.primaryButtonText, - disabled: this.props.primaryButtonDisabled || false, - onClick: this.props.onPrimaryButtonClick, - }; - const secondaryButtonProps: IButtonProps = - this.props.secondaryButtonText && this.props.onSecondaryButtonClick - ? { - text: this.props.secondaryButtonText, - onClick: this.props.onSecondaryButtonClick, - } - : undefined; + showCloseButton: showCloseButton || false, + onDismiss, + }, + modalProps: { isBlocking: isModal, isDarkOverlay: false }, + minWidth: DIALOG_MIN_WIDTH, + maxWidth: DIALOG_MAX_WIDTH, + }; - return ( - - {choiceGroupProps && } - {textFieldProps && } - {linkProps && ( - - {linkProps.linkText} - - )} - {progressIndicatorProps && } - - - {secondaryButtonProps && } - - - ); - } -} + const primaryButtonProps: IButtonProps = { + text: primaryButtonText, + disabled: primaryButtonDisabled || false, + onClick: onPrimaryButtonClick, + }; + const secondaryButtonProps: IButtonProps = + secondaryButtonText && onSecondaryButtonClick + ? { + text: secondaryButtonText, + onClick: onSecondaryButtonClick, + } + : undefined; + + return ( + + {choiceGroupProps && } + {textFieldProps && } + {linkProps && ( + + {linkProps.linkText} + + )} + {progressIndicatorProps && } + + + {secondaryButtonProps && } + + + ); +}; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx index 538a8249c..69ee13439 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx @@ -5,6 +5,7 @@ import { updateCollection } from "../../../Common/dataAccess/updateCollection"; import { updateOffer } from "../../../Common/dataAccess/updateOffer"; import * as DataModels from "../../../Contracts/DataModels"; import * as ViewModels from "../../../Contracts/ViewModels"; +import { updateUserContext } from "../../../UserContext"; import Explorer from "../../Explorer"; import { CollectionSettingsTabV2 } from "../../Tabs/SettingsTabV2"; import { SettingsComponent, SettingsComponentProps, SettingsComponentState } from "./SettingsComponent"; @@ -38,7 +39,6 @@ describe("SettingsComponent", () => { tabPath: "", node: undefined, hashLocation: "settings", - isActive: ko.observable(false), onUpdateTabsButtons: undefined, }), }; @@ -107,7 +107,13 @@ describe("SettingsComponent", () => { expect(settingsComponentInstance.shouldShowKeyspaceSharedThroughputMessage()).toEqual(false); const newContainer = new Explorer(); - newContainer.isPreferredApiCassandra = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableCassandra" }], + }, + } as DataModels.DatabaseAccount, + }); const newCollection = { ...collection }; newCollection.container = newContainer; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 8aa91f50e..4c151eb51 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -137,7 +137,7 @@ export class SettingsComponent extends React.Component - this.container && this.container.isPreferredApiCassandra() && hasDatabaseSharedThroughput(this.collection); + this.container && userContext.apiType === "Cassandra" && hasDatabaseSharedThroughput(this.collection); public hasConflictResolution = (): boolean => this.container?.databaseAccount && diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.test.tsx index ac36a4e60..2d25f9da7 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.test.tsx @@ -1,6 +1,7 @@ import { shallow } from "enzyme"; -import ko from "knockout"; import React from "react"; +import { DatabaseAccount } from "../../../../Contracts/DataModels"; +import { updateUserContext } from "../../../../UserContext"; import Explorer from "../../../Explorer"; import { ChangeFeedPolicyState, GeospatialConfigType, TtlOff, TtlOn, TtlOnNoDefault, TtlType } from "../SettingsUtils"; import { collection, container } from "../TestUtils"; @@ -104,8 +105,13 @@ describe("SubSettingsComponent", () => { it("partitionKey not visible", () => { const newContainer = new Explorer(); - - newContainer.isPreferredApiCassandra = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableCassandra" }], + }, + } as DatabaseAccount, + }); const props = { ...baseProps, container: newContainer }; const subSettingsComponent = new SubSettingsComponent(props); expect(subSettingsComponent.getPartitionKeyVisible()).toEqual(false); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.tsx index fd0cb538e..14947f81c 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/SubSettingsComponent.tsx @@ -320,8 +320,8 @@ export class SubSettingsComponent extends React.Component { if ( - this.props.container.isPreferredApiCassandra() || - this.props.container.isPreferredApiTable() || + userContext.apiType === "Cassandra" || + userContext.apiType === "Tables" || !this.props.collection.partitionKeyProperty || (this.props.container.isPreferredApiMongoDB() && this.props.collection.partitionKey.systemKey) ) { diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap index d517bea32..4fde12349 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap @@ -177,42 +177,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, EditTableEntityPane { "addButtonLabel": "Add Property", "attributeNameLabel": "Property Name", @@ -247,22 +211,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, CassandraAddCollectionPane { "autoPilotUsageCost": [Function], "canConfigureThroughput": [Function], @@ -324,20 +272,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, ], "_refreshSparkEnabledStateForAccount": [Function], "_resetNotebookWorkspace": [Function], @@ -467,42 +401,6 @@ exports[`SettingsComponent renders 1`] = ` "visible": [Function], }, "addDatabaseText": [Function], - "addTableEntityPane": AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, "arcadiaToken": [Function], "canExceedMaximumValue": [Function], "canSaveQueries": [Function], @@ -638,7 +536,6 @@ exports[`SettingsComponent renders 1`] = ` "hasStorageAnalyticsAfecFeature": [Function], "isAccountReady": [Function], "isAutoscaleDefaultEnabled": [Function], - "isCopyNotebookPaneEnabled": [Function], "isEnableMongoCapabilityPresent": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], "isGitHubPaneEnabled": [Function], @@ -647,10 +544,7 @@ exports[`SettingsComponent renders 1`] = ` "isMongoIndexingEnabled": [Function], "isNotebookEnabled": [Function], "isNotebooksEnabledForAccount": [Function], - "isPreferredApiCassandra": [Function], - "isPreferredApiGraph": [Function], "isPreferredApiMongoDB": [Function], - "isPreferredApiTable": [Function], "isPublishNotebookPaneEnabled": [Function], "isResourceTokenCollectionNodeSelected": [Function], "isRightPanelV2Enabled": [Function], @@ -661,22 +555,6 @@ exports[`SettingsComponent renders 1`] = ` "isSynapseLinkUpdating": [Function], "isTabsContentExpanded": [Function], "memoryUsageInfo": [Function], - "newVertexPane": NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, "notebookBasePath": [Function], "notebookServerInfo": [Function], "onRefreshDatabasesKeyPress": [Function], @@ -724,20 +602,6 @@ exports[`SettingsComponent renders 1`] = ` "setInProgressConsoleDataIdToBeDeleted": undefined, "setIsNotificationConsoleExpanded": undefined, "setNotificationConsoleData": undefined, - "setupNotebooksPane": SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, "signInAad": [Function], "sparkClusterConnectionInfo": [Function], "splitter": Splitter { @@ -941,42 +805,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, EditTableEntityPane { "addButtonLabel": "Add Property", "attributeNameLabel": "Property Name", @@ -1011,22 +839,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, CassandraAddCollectionPane { "autoPilotUsageCost": [Function], "canConfigureThroughput": [Function], @@ -1088,20 +900,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, ], "_refreshSparkEnabledStateForAccount": [Function], "_resetNotebookWorkspace": [Function], @@ -1231,42 +1029,6 @@ exports[`SettingsComponent renders 1`] = ` "visible": [Function], }, "addDatabaseText": [Function], - "addTableEntityPane": AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, "arcadiaToken": [Function], "canExceedMaximumValue": [Function], "canSaveQueries": [Function], @@ -1402,7 +1164,6 @@ exports[`SettingsComponent renders 1`] = ` "hasStorageAnalyticsAfecFeature": [Function], "isAccountReady": [Function], "isAutoscaleDefaultEnabled": [Function], - "isCopyNotebookPaneEnabled": [Function], "isEnableMongoCapabilityPresent": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], "isGitHubPaneEnabled": [Function], @@ -1411,10 +1172,7 @@ exports[`SettingsComponent renders 1`] = ` "isMongoIndexingEnabled": [Function], "isNotebookEnabled": [Function], "isNotebooksEnabledForAccount": [Function], - "isPreferredApiCassandra": [Function], - "isPreferredApiGraph": [Function], "isPreferredApiMongoDB": [Function], - "isPreferredApiTable": [Function], "isPublishNotebookPaneEnabled": [Function], "isResourceTokenCollectionNodeSelected": [Function], "isRightPanelV2Enabled": [Function], @@ -1425,22 +1183,6 @@ exports[`SettingsComponent renders 1`] = ` "isSynapseLinkUpdating": [Function], "isTabsContentExpanded": [Function], "memoryUsageInfo": [Function], - "newVertexPane": NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, "notebookBasePath": [Function], "notebookServerInfo": [Function], "onRefreshDatabasesKeyPress": [Function], @@ -1488,20 +1230,6 @@ exports[`SettingsComponent renders 1`] = ` "setInProgressConsoleDataIdToBeDeleted": undefined, "setIsNotificationConsoleExpanded": undefined, "setNotificationConsoleData": undefined, - "setupNotebooksPane": SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, "signInAad": [Function], "sparkClusterConnectionInfo": [Function], "splitter": Splitter { @@ -1718,42 +1446,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, EditTableEntityPane { "addButtonLabel": "Add Property", "attributeNameLabel": "Property Name", @@ -1788,22 +1480,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, CassandraAddCollectionPane { "autoPilotUsageCost": [Function], "canConfigureThroughput": [Function], @@ -1865,20 +1541,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, ], "_refreshSparkEnabledStateForAccount": [Function], "_resetNotebookWorkspace": [Function], @@ -2008,42 +1670,6 @@ exports[`SettingsComponent renders 1`] = ` "visible": [Function], }, "addDatabaseText": [Function], - "addTableEntityPane": AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, "arcadiaToken": [Function], "canExceedMaximumValue": [Function], "canSaveQueries": [Function], @@ -2179,7 +1805,6 @@ exports[`SettingsComponent renders 1`] = ` "hasStorageAnalyticsAfecFeature": [Function], "isAccountReady": [Function], "isAutoscaleDefaultEnabled": [Function], - "isCopyNotebookPaneEnabled": [Function], "isEnableMongoCapabilityPresent": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], "isGitHubPaneEnabled": [Function], @@ -2188,10 +1813,7 @@ exports[`SettingsComponent renders 1`] = ` "isMongoIndexingEnabled": [Function], "isNotebookEnabled": [Function], "isNotebooksEnabledForAccount": [Function], - "isPreferredApiCassandra": [Function], - "isPreferredApiGraph": [Function], "isPreferredApiMongoDB": [Function], - "isPreferredApiTable": [Function], "isPublishNotebookPaneEnabled": [Function], "isResourceTokenCollectionNodeSelected": [Function], "isRightPanelV2Enabled": [Function], @@ -2202,22 +1824,6 @@ exports[`SettingsComponent renders 1`] = ` "isSynapseLinkUpdating": [Function], "isTabsContentExpanded": [Function], "memoryUsageInfo": [Function], - "newVertexPane": NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, "notebookBasePath": [Function], "notebookServerInfo": [Function], "onRefreshDatabasesKeyPress": [Function], @@ -2265,20 +1871,6 @@ exports[`SettingsComponent renders 1`] = ` "setInProgressConsoleDataIdToBeDeleted": undefined, "setIsNotificationConsoleExpanded": undefined, "setNotificationConsoleData": undefined, - "setupNotebooksPane": SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, "signInAad": [Function], "sparkClusterConnectionInfo": [Function], "splitter": Splitter { @@ -2482,42 +2074,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, EditTableEntityPane { "addButtonLabel": "Add Property", "attributeNameLabel": "Property Name", @@ -2552,22 +2108,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, CassandraAddCollectionPane { "autoPilotUsageCost": [Function], "canConfigureThroughput": [Function], @@ -2629,20 +2169,6 @@ exports[`SettingsComponent renders 1`] = ` "title": [Function], "visible": [Function], }, - SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, ], "_refreshSparkEnabledStateForAccount": [Function], "_resetNotebookWorkspace": [Function], @@ -2772,42 +2298,6 @@ exports[`SettingsComponent renders 1`] = ` "visible": [Function], }, "addDatabaseText": [Function], - "addTableEntityPane": AddTableEntityPane { - "addButtonLabel": "Add Property", - "attributeNameLabel": "Property Name", - "attributeValueLabel": "Value", - "canAdd": [Function], - "canApply": [Function], - "container": [Circular], - "dataTypeLabel": "Type", - "displayedAttributes": [Function], - "editAttribute": [Function], - "editButtonLabel": "Edit", - "editingProperty": [Function], - "edmTypes": [Function], - "enterRequiredValueLabel": "Enter identifier value.", - "enterValueLabel": "Enter value to keep property.", - "finishEditingAttribute": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "addtableentitypane", - "insertAttribute": [Function], - "isEditing": [Function], - "isExecuting": [Function], - "isTemplateReady": [Function], - "onAddPropertyKeyDown": [Function], - "onBackButtonKeyDown": [Function], - "onDeletePropertyKeyDown": [Function], - "onEditPropertyKeyDown": [Function], - "onKeyUp": [Function], - "removeAttribute": [Function], - "removeButtonLabel": "Remove", - "scrollId": [Function], - "submitButtonText": [Function], - "title": [Function], - "visible": [Function], - }, "arcadiaToken": [Function], "canExceedMaximumValue": [Function], "canSaveQueries": [Function], @@ -2943,7 +2433,6 @@ exports[`SettingsComponent renders 1`] = ` "hasStorageAnalyticsAfecFeature": [Function], "isAccountReady": [Function], "isAutoscaleDefaultEnabled": [Function], - "isCopyNotebookPaneEnabled": [Function], "isEnableMongoCapabilityPresent": [Function], "isFixedCollectionWithSharedThroughputSupported": [Function], "isGitHubPaneEnabled": [Function], @@ -2952,10 +2441,7 @@ exports[`SettingsComponent renders 1`] = ` "isMongoIndexingEnabled": [Function], "isNotebookEnabled": [Function], "isNotebooksEnabledForAccount": [Function], - "isPreferredApiCassandra": [Function], - "isPreferredApiGraph": [Function], "isPreferredApiMongoDB": [Function], - "isPreferredApiTable": [Function], "isPublishNotebookPaneEnabled": [Function], "isResourceTokenCollectionNodeSelected": [Function], "isRightPanelV2Enabled": [Function], @@ -2966,22 +2452,6 @@ exports[`SettingsComponent renders 1`] = ` "isSynapseLinkUpdating": [Function], "isTabsContentExpanded": [Function], "memoryUsageInfo": [Function], - "newVertexPane": NewVertexPane { - "buildString": [Function], - "container": [Circular], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "newvertexpane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onMoreDetailsKeyPress": [Function], - "onSubmitCreateCallback": null, - "partitionKeyProperty": [Function], - "tempVertexData": [Function], - "title": [Function], - "visible": [Function], - }, "notebookBasePath": [Function], "notebookServerInfo": [Function], "onRefreshDatabasesKeyPress": [Function], @@ -3029,20 +2499,6 @@ exports[`SettingsComponent renders 1`] = ` "setInProgressConsoleDataIdToBeDeleted": undefined, "setIsNotificationConsoleExpanded": undefined, "setNotificationConsoleData": undefined, - "setupNotebooksPane": SetupNotebooksPane { - "container": [Circular], - "description": [Function], - "firstFieldHasFocus": [Function], - "formErrors": [Function], - "formErrorsDetails": [Function], - "id": "setupnotebookspane", - "isExecuting": [Function], - "isTemplateReady": [Function], - "onCompleteSetupClick": [Function], - "onCompleteSetupKeyPress": [Function], - "title": [Function], - "visible": [Function], - }, "signInAad": [Function], "sparkClusterConnectionInfo": [Function], "splitter": Splitter { diff --git a/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts b/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts index 0d7f7cbbc..3b81ff56a 100644 --- a/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts +++ b/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts @@ -14,10 +14,7 @@ describe("ContainerSampleGenerator", () => { const createExplorerStub = (database: ViewModels.Database): Explorer => { const explorerStub = {} as Explorer; explorerStub.databases = ko.observableArray([database]); - explorerStub.isPreferredApiGraph = ko.computed(() => false); explorerStub.isPreferredApiMongoDB = ko.computed(() => false); - explorerStub.isPreferredApiTable = ko.computed(() => false); - explorerStub.isPreferredApiCassandra = ko.computed(() => false); explorerStub.canExceedMaximumValue = ko.computed(() => false); explorerStub.findDatabaseWithId = () => database; explorerStub.refreshAllDatabases = () => Q.resolve(); @@ -116,7 +113,13 @@ describe("ContainerSampleGenerator", () => { collection.databaseId = database.id(); const explorerStub = createExplorerStub(database); - explorerStub.isPreferredApiGraph = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableGremlin" }], + }, + } as DatabaseAccount, + }); const generator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub); generator.setData(sampleData); @@ -156,8 +159,6 @@ describe("ContainerSampleGenerator", () => { it("should not create any sample for Cassandra API account", async () => { const experience = "Sample generation not supported for this API Cassandra"; - const explorerStub = createExplorerStub(undefined); - updateUserContext({ databaseAccount: { properties: { @@ -165,6 +166,7 @@ describe("ContainerSampleGenerator", () => { }, } as DatabaseAccount, }); + const explorerStub = createExplorerStub(undefined); // Rejects with error that contains experience await expect(ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub)).rejects.toMatch(experience); }); diff --git a/src/Explorer/DataSamples/ContainerSampleGenerator.ts b/src/Explorer/DataSamples/ContainerSampleGenerator.ts index 9e7c83fed..7d6b42453 100644 --- a/src/Explorer/DataSamples/ContainerSampleGenerator.ts +++ b/src/Explorer/DataSamples/ContainerSampleGenerator.ts @@ -73,7 +73,7 @@ export class ContainerSampleGenerator { } const promises: Q.Promise[] = []; - if (this.container.isPreferredApiGraph()) { + if (userContext.apiType === "Gremlin") { // For Gremlin, all queries are executed sequentially, because some queries might be dependent on other queries // (e.g. adding edge requires vertices to be present) const queries: string[] = this.sampleDataFile.data; diff --git a/src/Explorer/DataSamples/DataSamplesUtil.ts b/src/Explorer/DataSamples/DataSamplesUtil.ts index 284192c0e..63b35cfff 100644 --- a/src/Explorer/DataSamples/DataSamplesUtil.ts +++ b/src/Explorer/DataSamples/DataSamplesUtil.ts @@ -1,8 +1,7 @@ import * as ViewModels from "../../Contracts/ViewModels"; import { userContext } from "../../UserContext"; -import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; +import { logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import Explorer from "../Explorer"; -import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; export class DataSamplesUtil { @@ -21,18 +20,16 @@ export class DataSamplesUtil { if (this.hasContainer(databaseName, containerName, this.container.databases())) { const msg = `The container ${containerName} in database ${databaseName} already exists. Please delete it and retry.`; this.container.showOkModalDialog(DataSamplesUtil.DialogTitle, msg); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); return; } await generator .createSampleContainerAsync() - .catch((error) => - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, `Error creating sample container: ${error}`) - ); + .catch((error) => logConsoleError(`Error creating sample container: ${error}`)); const msg = `The sample ${containerName} in database ${databaseName} has been successfully created.`; this.container.showOkModalDialog(DataSamplesUtil.DialogTitle, msg); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, msg); + logConsoleInfo(msg); } /** @@ -57,6 +54,6 @@ export class DataSamplesUtil { } public isSampleContainerCreationSupported(): boolean { - return userContext.apiType === "SQL" || this.container.isPreferredApiGraph(); + return userContext.apiType === "SQL" || userContext.apiType === "Gremlin"; } } diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 6883ab29c..5e289f1f7 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -36,6 +36,7 @@ import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationU import { stringToBlob } from "../Utils/BlobUtils"; import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils"; import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils"; +import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../Utils/NotificationConsoleUtils"; import * as PricingUtils from "../Utils/PricingUtils"; import * as ComponentRegisterer from "./ComponentRegisterer"; import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker"; @@ -43,34 +44,35 @@ import { CommandButtonComponentProps } from "./Controls/CommandButton/CommandBut import { DialogProps, TextFieldProps } from "./Controls/Dialog"; import { GalleryTab } from "./Controls/NotebookGallery/GalleryViewerComponent"; import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter"; -import { ConsoleData, ConsoleDataType } from "./Menus/NotificationConsole/NotificationConsoleComponent"; +import { ConsoleData } from "./Menus/NotificationConsole/NotificationConsoleComponent"; import * as FileSystemUtil from "./Notebook/FileSystemUtil"; import { NotebookContentItem, NotebookContentItemType } from "./Notebook/NotebookContentItem"; import { NotebookUtil } from "./Notebook/NotebookUtil"; import AddCollectionPane from "./Panes/AddCollectionPane"; import { AddCollectionPanel } from "./Panes/AddCollectionPanel"; import AddDatabasePane from "./Panes/AddDatabasePane"; -import { BrowseQueriesPanel } from "./Panes/BrowseQueriesPanel"; +import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane/BrowseQueriesPane"; import CassandraAddCollectionPane from "./Panes/CassandraAddCollectionPane"; import { ContextualPaneBase } from "./Panes/ContextualPaneBase"; -import { DeleteCollectionConfirmationPanel } from "./Panes/DeleteCollectionConfirmationPanel"; +import { DeleteCollectionConfirmationPane } from "./Panes/DeleteCollectionConfirmationPane/DeleteCollectionConfirmationPane"; import { DeleteDatabaseConfirmationPanel } from "./Panes/DeleteDatabaseConfirmationPanel"; -import { ExecuteSprocParamsPanel } from "./Panes/ExecuteSprocParamsPanel"; +import { ExecuteSprocParamsPane } from "./Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane"; import GraphStylingPane from "./Panes/GraphStylingPane"; -import { LoadQueryPanel } from "./Panes/LoadQueryPanel"; -import NewVertexPane from "./Panes/NewVertexPane"; -import { SaveQueryPanel } from "./Panes/SaveQueryPanel"; -import { SettingsPane } from "./Panes/SettingsPane"; -import { SetupNotebooksPane } from "./Panes/SetupNotebooksPane"; +import { LoadQueryPane } from "./Panes/LoadQueryPane/LoadQueryPane"; +import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane"; +import { SettingsPane } from "./Panes/SettingsPane/SettingsPane"; +import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel"; import { StringInputPane } from "./Panes/StringInputPane"; -import AddTableEntityPane from "./Panes/Tables/AddTableEntityPane"; +import { AddTableEntityPanel } from "./Panes/Tables/AddTableEntityPanel"; import EditTableEntityPane from "./Panes/Tables/EditTableEntityPane"; import { TableQuerySelectPanel } from "./Panes/Tables/TableQuerySelectPanel"; -import { UploadFilePane } from "./Panes/UploadFilePane"; -import { UploadItemsPane } from "./Panes/UploadItemsPane"; +import { UploadFilePane } from "./Panes/UploadFilePane/UploadFilePane"; +import { UploadItemsPane } from "./Panes/UploadItemsPane/UploadItemsPane"; +import TableListViewModal from "./Tables/DataTable/TableEntityListViewModel"; import QueryViewModel from "./Tables/QueryBuilder/QueryViewModel"; import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient"; import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab"; +import QueryTablesTab from "./Tabs/QueryTablesTab"; import TabsBase from "./Tabs/TabsBase"; import { TabsManager } from "./Tabs/TabsManager"; import TerminalTab from "./Tabs/TerminalTab"; @@ -116,26 +118,11 @@ export default class Explorer { * Use userContext.apiType instead * */ public defaultExperience: ko.Observable; - /** - * @deprecated - * Compare a string with userContext.apiType instead: userContext.apiType === "Cassandra" - * */ - public isPreferredApiCassandra: ko.Computed; /** * @deprecated * Compare a string with userContext.apiType instead: userContext.apiType === "Mongo" * */ public isPreferredApiMongoDB: ko.Computed; - /** - * @deprecated - * Compare a string with userContext.apiType instead: userContext.apiType === "Gremlin" - * */ - public isPreferredApiGraph: ko.Computed; - /** - * @deprecated - * Compare a string with userContext.apiType instead: userContext.apiType === "Tables" - * */ - public isPreferredApiTable: ko.Computed; public isFixedCollectionWithSharedThroughputSupported: ko.Computed; /** * @deprecated @@ -186,20 +173,15 @@ export default class Explorer { public addDatabasePane: AddDatabasePane; public addCollectionPane: AddCollectionPane; public graphStylingPane: GraphStylingPane; - public addTableEntityPane: AddTableEntityPane; public editTableEntityPane: EditTableEntityPane; - public newVertexPane: NewVertexPane; public cassandraAddCollectionPane: CassandraAddCollectionPane; public stringInputPane: StringInputPane; - public setupNotebooksPane: SetupNotebooksPane; public gitHubReposPane: ContextualPaneBase; public publishNotebookPaneAdapter: ReactAdapter; - public copyNotebookPaneAdapter: ReactAdapter; // features public isGitHubPaneEnabled: ko.Observable; public isPublishNotebookPaneEnabled: ko.Observable; - public isCopyNotebookPaneEnabled: ko.Observable; public isHostedDataExplorerEnabled: ko.Computed; public isRightPanelV2Enabled: ko.Computed; public isMongoIndexingEnabled: ko.Observable; @@ -297,7 +279,6 @@ export default class Explorer { ((await this._containsDefaultNotebookWorkspace(this.databaseAccount())) || userContext.features.enableNotebooks) ); - TelemetryProcessor.trace(Action.NotebookEnabled, ActionModifiers.Mark, { isNotebookEnabled: this.isNotebookEnabled(), dataExplorerArea: Constants.Areas.Notebook, @@ -350,7 +331,6 @@ export default class Explorer { this.isGitHubPaneEnabled = ko.observable(false); this.isMongoIndexingEnabled = ko.observable(false); this.isPublishNotebookPaneEnabled = ko.observable(false); - this.isCopyNotebookPaneEnabled = ko.observable(false); this.canExceedMaximumValue = ko.computed(() => userContext.features.canExceedMaximumValue); @@ -414,20 +394,6 @@ export default class Explorer { }); }); - this.isPreferredApiCassandra = ko.computed(() => { - const defaultExperience = (this.defaultExperience && this.defaultExperience()) || ""; - return defaultExperience.toLowerCase() === Constants.DefaultAccountExperience.Cassandra.toLowerCase(); - }); - this.isPreferredApiGraph = ko.computed(() => { - const defaultExperience = (this.defaultExperience && this.defaultExperience()) || ""; - return defaultExperience.toLowerCase() === Constants.DefaultAccountExperience.Graph.toLowerCase(); - }); - - this.isPreferredApiTable = ko.computed(() => { - const defaultExperience = (this.defaultExperience && this.defaultExperience()) || ""; - return defaultExperience.toLowerCase() === Constants.DefaultAccountExperience.Table.toLowerCase(); - }); - this.isFixedCollectionWithSharedThroughputSupported = ko.computed(() => { if (userContext.features.enableFixedCollectionWithSharedThroughput) { return true; @@ -486,7 +452,9 @@ export default class Explorer { this.isHostedDataExplorerEnabled = ko.computed( () => - configContext.platform === Platform.Portal && !this.isRunningOnNationalCloud() && !this.isPreferredApiGraph() + configContext.platform === Platform.Portal && + !this.isRunningOnNationalCloud() && + userContext.apiType !== "Gremlin" ); this.isRightPanelV2Enabled = ko.computed(() => userContext.features.enableRightPanelV2); this.selectedDatabaseId = ko.computed(() => { @@ -518,7 +486,7 @@ export default class Explorer { }); this.addCollectionPane = new AddCollectionPane({ - isPreferredApiTable: ko.computed(() => this.isPreferredApiTable()), + isPreferredApiTable: ko.computed(() => userContext.apiType === "Tables"), id: "addcollectionpane", visible: ko.observable(false), @@ -532,13 +500,6 @@ export default class Explorer { container: this, }); - this.addTableEntityPane = new AddTableEntityPane({ - id: "addtableentitypane", - visible: ko.observable(false), - - container: this, - }); - this.editTableEntityPane = new EditTableEntityPane({ id: "edittableentitypane", visible: ko.observable(false), @@ -546,13 +507,6 @@ export default class Explorer { container: this, }); - this.newVertexPane = new NewVertexPane({ - id: "newvertexpane", - visible: ko.observable(false), - - container: this, - }); - this.cassandraAddCollectionPane = new CassandraAddCollectionPane({ id: "cassandraaddcollectionpane", visible: ko.observable(false), @@ -567,25 +521,21 @@ export default class Explorer { container: this, }); - this.setupNotebooksPane = new SetupNotebooksPane({ - id: "setupnotebookspane", - visible: ko.observable(false), - - container: this, - }); - this.tabsManager = params?.tabsManager ?? new TabsManager(); + this.tabsManager.openedTabs.subscribe((tabs) => { + if (tabs.length === 0) { + this.selectedNode(undefined); + this.onUpdateTabsButtons([]); + } + }); this._panes = [ this.addDatabasePane, this.addCollectionPane, this.graphStylingPane, - this.addTableEntityPane, this.editTableEntityPane, - this.newVertexPane, this.cassandraAddCollectionPane, this.stringInputPane, - this.setupNotebooksPane, ]; this.addDatabaseText.subscribe((addDatabaseText: string) => this.addDatabasePane.title(addDatabaseText)); this.isTabsContentExpanded = ko.observable(false); @@ -654,7 +604,6 @@ export default class Explorer { this.addCollectionPane.collectionIdTitle("Table id"); this.addCollectionPane.collectionWithThroughputInSharedTitle("Provision dedicated throughput for this table"); this.refreshTreeTitle("Refresh tables"); - this.addTableEntityPane.title("Add Table Entity"); this.editTableEntityPane.title("Edit Table Entity"); this.tableDataClient = new TablesAPIDataClient(); break; @@ -669,7 +618,6 @@ export default class Explorer { this.addCollectionPane.collectionIdTitle("Table id"); this.addCollectionPane.collectionWithThroughputInSharedTitle("Provision dedicated throughput for this table"); this.refreshTreeTitle("Refresh tables"); - this.addTableEntityPane.title("Add Table Row"); this.editTableEntityPane.title("Edit Table Row"); this.tableDataClient = new CassandraAPIDataClient(); break; @@ -765,8 +713,7 @@ export default class Explorer { onPrimaryButtonClick: async () => { const startTime = TelemetryProcessor.traceStart(Action.EnableAzureSynapseLink); - const logId = NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.InProgress, + const clearInProgressMessage = logConsoleProgress( "Enabling Azure Synapse Link for this account. This may take a few minutes before you can enable analytical store for this account." ); this.isSynapseLinkUpdating(true); @@ -784,19 +731,13 @@ export default class Explorer { }, } ); - NotificationConsoleUtils.clearInProgressMessageWithId(logId); - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Info, - "Enabled Azure Synapse Link for this account" - ); + clearInProgressMessage(); + logConsoleInfo("Enabled Azure Synapse Link for this account"); TelemetryProcessor.traceSuccess(Action.EnableAzureSynapseLink, {}, startTime); this.databaseAccount(databaseAccount); } catch (error) { - NotificationConsoleUtils.clearInProgressMessageWithId(logId); - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Enabling Azure Synapse Link for this account failed. ${getErrorMessage(error)}` - ); + clearInProgressMessage(); + logConsoleError(`Enabling Azure Synapse Link for this account failed. ${getErrorMessage(error)}`); TelemetryProcessor.traceFailure(Action.EnableAzureSynapseLink, {}, startTime); } finally { this.isSynapseLinkUpdating(false); @@ -923,10 +864,7 @@ export default class Explorer { }, startKey ); - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Error while refreshing databases: ${errorMessage}` - ); + logConsoleError(`Error while refreshing databases: ${errorMessage}`); } ); @@ -1147,20 +1085,20 @@ export default class Explorer { private _resetNotebookWorkspace = async () => { this._closeModalDialog(); - const id = NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.InProgress, "Resetting notebook workspace"); + const clearInProgressMessage = logConsoleProgress("Resetting notebook workspace"); try { await this.notebookManager?.notebookClient.resetWorkspace(); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, "Successfully reset notebook workspace"); + logConsoleInfo("Successfully reset notebook workspace"); TelemetryProcessor.traceSuccess(Action.ResetNotebookWorkspace); } catch (error) { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, `Failed to reset notebook workspace: ${error}`); + logConsoleError(`Failed to reset notebook workspace: ${error}`); TelemetryProcessor.traceFailure(Action.ResetNotebookWorkspace, { error: getErrorMessage(error), errorStack: getErrorStack(error), }); throw error; } finally { - NotificationConsoleUtils.clearInProgressMessageWithId(id); + clearInProgressMessage(); } }; @@ -1495,11 +1433,7 @@ export default class Explorer { } public copyNotebook(name: string, content: string): void { - if (this.notebookManager) { - this.notebookManager.openCopyNotebookPane(name, content); - this.copyNotebookPaneAdapter = this.notebookManager.copyNotebookPaneAdapter; - this.isCopyNotebookPaneEnabled(true); - } + this.notebookManager?.openCopyNotebookPane(name, content); } public showOkModalDialog(title: string, msg: string): void { @@ -1586,7 +1520,6 @@ export default class Explorer { collection: null, masterKey: userContext.masterKey || "", hashLocation: "notebooks", - isActive: ko.observable(false), isTabsContentExpanded: ko.observable(true), onLoadStartKey: null, onUpdateTabsButtons: this.onUpdateTabsButtons, @@ -1718,11 +1651,7 @@ export default class Explorer { clearMessage(); }, (error: any) => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Could not download notebook ${getErrorMessage(error)}` - ); - + logConsoleError(`Could not download notebook ${getErrorMessage(error)}`); clearMessage(); } ); @@ -1874,15 +1803,8 @@ export default class Explorer { } return this.notebookManager?.notebookContentClient.deleteContentItem(item).then( - () => { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Successfully deleted: ${item.path}`); - }, - (reason: any) => { - NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.Error, - `Failed to delete "${item.path}": ${JSON.stringify(reason)}` - ); - } + () => logConsoleInfo(`Successfully deleted: ${item.path}`), + (reason: any) => logConsoleError(`Failed to delete "${item.path}": ${JSON.stringify(reason)}`) ); } @@ -1898,11 +1820,7 @@ export default class Explorer { parent = parent || this.resourceTree.myNotebooksContentRoot; - const notificationProgressId = NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.InProgress, - `Creating new notebook in ${parent.path}` - ); - + const clearInProgressMessage = logConsoleProgress(`Creating new notebook in ${parent.path}`); const startKey: number = TelemetryProcessor.traceStart(Action.CreateNewNotebook, { dataExplorerArea: Constants.Areas.Notebook, }); @@ -1910,7 +1828,7 @@ export default class Explorer { this.notebookManager?.notebookContentClient .createNewNotebookFile(parent) .then((newFile: NotebookContentItem) => { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Successfully created: ${newFile.name}`); + logConsoleInfo(`Successfully created: ${newFile.name}`); TelemetryProcessor.traceSuccess( Action.CreateNewNotebook, { @@ -1923,7 +1841,7 @@ export default class Explorer { .then(() => this.resourceTree.triggerRender()) .catch((error: any) => { const errorMessage = `Failed to create a new notebook: ${getErrorMessage(error)}`; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, errorMessage); + logConsoleError(errorMessage); TelemetryProcessor.traceFailure( Action.CreateNewNotebook, { @@ -1934,7 +1852,7 @@ export default class Explorer { startKey ); }) - .finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(notificationProgressId)); + .finally(clearInProgressMessage); } public refreshContentItem(item: NotebookContentItem): Promise { @@ -1992,7 +1910,6 @@ export default class Explorer { tabPath: title, collection: null, hashLocation: hashLocation, - isActive: ko.observable(false), isTabsContentExpanded: ko.observable(true), onLoadStartKey: null, onUpdateTabsButtons: this.onUpdateTabsButtons, @@ -2097,7 +2014,7 @@ export default class Explorer { } public onNewCollectionClicked(): void { - if (this.isPreferredApiCassandra()) { + if (userContext.apiType === "Cassandra") { this.cassandraAddCollectionPane.open(); } else if (userContext.features.enableReactPane) { this.openAddCollectionPanel(); @@ -2145,7 +2062,7 @@ export default class Explorer { const description = "You have not yet created a notebooks workspace for this account. To proceed and start using notebooks, we'll need to create a default notebooks workspace in this account."; - this.setupNotebooksPane.openWithTitleAndDescription(title, description); + this.openSetupNotebooksPanel(title, description); } public async handleOpenFileAction(path: string): Promise { @@ -2210,7 +2127,7 @@ export default class Explorer { let collectionName = PricingUtils.getCollectionName(userContext.defaultExperience); this.openSidePanel( "Delete " + collectionName, - this.closeSidePanel()} @@ -2262,15 +2179,15 @@ export default class Explorer { } public openBrowseQueriesPanel(): void { - this.openSidePanel("Open Saved Queries", ); + this.openSidePanel("Open Saved Queries", ); } public openLoadQueryPanel(): void { - this.openSidePanel("Load Query", this.closeSidePanel()} />); + this.openSidePanel("Load Query", this.closeSidePanel()} />); } public openSaveQueryPanel(): void { - this.openSidePanel("Save Query", this.closeSidePanel()} />); + this.openSidePanel("Save Query", this.closeSidePanel()} />); } public openUploadFilePanel(parent?: NotebookContentItem): void { @@ -2285,6 +2202,31 @@ export default class Explorer { ); } + public openAddTableEntityPanel(queryTablesTab: QueryTablesTab, tableEntityListViewModel: TableListViewModal): void { + this.openSidePanel( + "Add Table Entity", + + ); + } + public openSetupNotebooksPanel(title: string, description: string): void { + this.openSidePanel( + title, + this.expandConsole()} + panelTitle={title} + panelDescription={description} + /> + ); + } + public openTableSelectQueryPanel(queryViewModal: QueryViewModel): void { this.openSidePanel( "Select Column", diff --git a/src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts b/src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts index efe403eec..31a01f0a3 100644 --- a/src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts +++ b/src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts @@ -1,24 +1,22 @@ -import * as ko from "knockout"; -import Q from "q"; -import { schemeCategory10 } from "d3-scale-chromatic"; -import { selectAll, select } from "d3-selection"; -import { zoom, zoomIdentity } from "d3-zoom"; -import { scaleOrdinal } from "d3-scale"; -import { forceSimulation, forceLink, forceCollide, forceManyBody } from "d3-force"; -import { interpolateNumber, interpolate } from "d3-interpolate"; +import { BaseType } from "d3"; import { map as d3Map } from "d3-collection"; -import { drag, D3DragEvent } from "d3-drag"; - +import { D3DragEvent, drag } from "d3-drag"; +import { forceCollide, forceLink, forceManyBody, forceSimulation } from "d3-force"; +import { interpolate, interpolateNumber } from "d3-interpolate"; +import { scaleOrdinal } from "d3-scale"; +import { schemeCategory10 } from "d3-scale-chromatic"; +import { select, selectAll } from "d3-selection"; +import { zoom, zoomIdentity } from "d3-zoom"; +import * as ko from "knockout"; +import Q from "q"; import _ from "underscore"; -import { NeighborType } from "../../../Contracts/ViewModels"; -import { GraphData, D3Node, D3Link } from "./GraphData"; -import { HashMap } from "../../../Common/HashMap"; -import { BaseType } from "d3"; -import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; -import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; -import { GraphConfig } from "../../Tabs/GraphTab"; -import { GraphExplorer } from "./GraphExplorer"; import * as Constants from "../../../Common/Constants"; +import { HashMap } from "../../../Common/HashMap"; +import { NeighborType } from "../../../Contracts/ViewModels"; +import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; +import { GraphConfig } from "../../Tabs/GraphTab"; +import { D3Link, D3Node, GraphData } from "./GraphData"; +import { GraphExplorer } from "./GraphExplorer"; export interface D3GraphIconMap { [key: string]: { data: string; format: string }; @@ -1005,7 +1003,7 @@ export class D3ForceGraph implements GraphRenderer { */ private loadNeighbors(v: D3Node, pageAction: PAGE_ACTION) { if (!this.graphDataWrapper.hasVertexId(v.id)) { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, `Clicked node not in graph data. id: ${v.id}`); + logConsoleError(`Clicked node not in graph data. id: ${v.id}`); return; } diff --git a/src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx b/src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx index ba35d2fd8..bfd23f09c 100644 --- a/src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx +++ b/src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx @@ -1,37 +1,36 @@ +import { FeedOptions, ItemDefinition, QueryIterator, Resource } from "@azure/cosmos"; import * as Q from "q"; import * as React from "react"; -import * as LeftPane from "./LeftPaneComponent"; -import { MiddlePaneComponent } from "./MiddlePaneComponent"; -import * as InputTypeaheadComponent from "../../Controls/InputTypeahead/InputTypeaheadComponent"; -import * as NodeProperties from "./NodePropertiesComponent"; -import * as D3ForceGraph from "./D3ForceGraph"; -import { GraphVizComponentProps } from "./GraphVizComponent"; -import * as GraphData from "./GraphData"; -import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; -import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; -import * as GraphUtil from "./GraphUtil"; -import * as DataModels from "../../../Contracts/DataModels"; -import * as ViewModels from "../../../Contracts/ViewModels"; -import * as GremlinClient from "./GremlinClient"; -import * as StorageUtility from "../../../Shared/StorageUtility"; -import { ArraysByKeyCache } from "./ArraysByKeyCache"; -import { EdgeInfoCache } from "./EdgeInfoCache"; -import * as TabComponent from "../../Controls/Tabs/TabComponent"; -import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility"; -import { QueryContainerComponent } from "./QueryContainerComponent"; -import { GraphConfig } from "../../Tabs/GraphTab"; -import { EditorReact } from "../../Controls/Editor/EditorReact"; import LoadGraphIcon from "../../../../images/LoadGraph.png"; -import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; -import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; -import * as Constants from "../../../Common/Constants"; -import { InputProperty } from "../../../Contracts/ViewModels"; -import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos"; import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif"; +import * as Constants from "../../../Common/Constants"; import { queryDocuments } from "../../../Common/dataAccess/queryDocuments"; import { queryDocumentsPage } from "../../../Common/dataAccess/queryDocumentsPage"; import { getErrorMessage } from "../../../Common/ErrorHandlingUtils"; -import { FeedOptions } from "@azure/cosmos"; +import * as DataModels from "../../../Contracts/DataModels"; +import * as ViewModels from "../../../Contracts/ViewModels"; +import { InputProperty } from "../../../Contracts/ViewModels"; +import * as StorageUtility from "../../../Shared/StorageUtility"; +import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility"; +import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; +import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; +import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils"; +import { EditorReact } from "../../Controls/Editor/EditorReact"; +import * as InputTypeaheadComponent from "../../Controls/InputTypeahead/InputTypeaheadComponent"; +import * as TabComponent from "../../Controls/Tabs/TabComponent"; +import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; +import { GraphConfig } from "../../Tabs/GraphTab"; +import { ArraysByKeyCache } from "./ArraysByKeyCache"; +import * as D3ForceGraph from "./D3ForceGraph"; +import { EdgeInfoCache } from "./EdgeInfoCache"; +import * as GraphData from "./GraphData"; +import * as GraphUtil from "./GraphUtil"; +import { GraphVizComponentProps } from "./GraphVizComponent"; +import * as GremlinClient from "./GremlinClient"; +import * as LeftPane from "./LeftPaneComponent"; +import { MiddlePaneComponent } from "./MiddlePaneComponent"; +import * as NodeProperties from "./NodePropertiesComponent"; +import { QueryContainerComponent } from "./QueryContainerComponent"; export interface GraphAccessor { applyFilter: () => void; @@ -697,13 +696,13 @@ export class GraphExplorer extends React.Component { - const id = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${cmd}`); + const clearConsoleProgress = GraphExplorer.reportToConsole(ConsoleDataType.InProgress, `Executing: ${cmd}`); this.setExecuteCounter(this.executeCounter + 1); return this.gremlinClient.execute(cmd).then( (result: GremlinClient.GremlinRequestResult) => { this.setExecuteCounter(this.executeCounter - 1); - GraphExplorer.clearConsoleProgress(id); + clearConsoleProgress(); if (result.isIncomplete) { const msg = `The query results are too large and only partial results are displayed for: ${cmd}`; GraphExplorer.reportToConsole(ConsoleDataType.Error, msg); @@ -718,7 +717,7 @@ export class GraphExplorer extends React.Component { this.setExecuteCounter(this.executeCounter - 1); GraphExplorer.reportToConsole(ConsoleDataType.Error, `Gremlin query failed: ${cmd}`, err); - GraphExplorer.clearConsoleProgress(id); + clearConsoleProgress(); throw err; } ); @@ -1083,13 +1082,26 @@ export class GraphExplorer extends React.Component void; + public static reportToConsole(type: ConsoleDataType.Info, msg: string, ...errorData: any[]): void; + public static reportToConsole(type: ConsoleDataType.Error, msg: string, ...errorData: any[]): void; + public static reportToConsole(type: ConsoleDataType, msg: string, ...errorData: any[]): void | (() => void) { let errorDataStr: string = ""; if (errorData && errorData.length > 0) { console.error(msg, errorData); errorDataStr = ": " + JSON.stringify(errorData); } - return NotificationConsoleUtils.logConsoleMessage(type, `${msg}${errorDataStr}`); + + const consoleMessage = `${msg}${errorDataStr}`; + + switch (type) { + case ConsoleDataType.Error: + return logConsoleError(consoleMessage); + case ConsoleDataType.Info: + return logConsoleInfo(consoleMessage); + case ConsoleDataType.InProgress: + return logConsoleProgress(consoleMessage); + } } private setNodePropertiesViewMode(viewMode: NodeProperties.Mode) { @@ -1368,7 +1380,7 @@ export class GraphExplorer extends React.Component ); } - - private static clearConsoleProgress(id: string) { - NotificationConsoleUtils.clearInProgressMessageWithId(id); - } } diff --git a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts index 6daf7ea23..ee022b873 100644 --- a/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts +++ b/src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts @@ -3,11 +3,10 @@ */ import * as Q from "q"; -import { GremlinSimpleClient, Result } from "./GremlinSimpleClient"; -import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; -import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; -import { HashMap } from "../../../Common/HashMap"; import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils"; +import { HashMap } from "../../../Common/HashMap"; +import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils"; +import { GremlinSimpleClient, Result } from "./GremlinSimpleClient"; export interface GremlinClientParameters { endpoint: string; @@ -77,9 +76,7 @@ export class GremlinClient { this.abortPendingRequest(requestId, errorMessage, result.requestCharge); } }, - infoCallback: (msg: string) => { - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, msg); - }, + infoCallback: logConsoleInfo, }); } diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts b/src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts deleted file mode 100644 index 6327f9d28..000000000 --- a/src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as ko from "knockout"; -import { NewVertexComponent, NewVertexViewModel } from "./NewVertexComponent"; - -const component = NewVertexComponent; - -describe("New Vertex Component", () => { - let vm: NewVertexViewModel; - let partitionKeyProperty: ko.Observable; - - beforeEach(async () => { - document.body.innerHTML = component.template as any; - partitionKeyProperty = ko.observable(null); - vm = new component.viewModel({ - newVertexData: null, - partitionKeyProperty, - }); - ko.applyBindings(vm); - }); - - afterEach(() => { - ko.cleanNode(document); - }); - - describe("Rendering", () => { - it("should display property list with input and +Add Property", () => { - expect(document.querySelector(".newVertexComponent .newVertexForm")).not.toBeNull(); - expect(document.querySelector(".newVertexComponent .edgeInput")).not.toBeNull(); - expect(document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn")).not.toBeNull(); - }); - - it("should display partition key property if set", () => { - partitionKeyProperty("testKey"); - expect( - (document.querySelector(".newVertexComponent .newVertexForm .labelCol input") as HTMLInputElement).value - ).toEqual("testKey"); - }); - - it("should NOT display partition key property if NOT set", () => { - expect(document.getElementsByClassName("valueCol").length).toBe(0); - }); - }); - - describe("Behavior", () => { - let clickSpy: jasmine.Spy; - - beforeEach(() => { - clickSpy = jasmine.createSpy("Command button click spy"); - }); - - it("should add new property row when +Add property button is pressed", () => { - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - expect(document.getElementsByClassName("valueCol").length).toBe(3); - expect(document.getElementsByClassName("rightPaneTrashIcon").length).toBe(3); - }); - - it("should remove property row when trash button is pressed", () => { - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - - // Mark this one to delete - const elts = document.querySelectorAll(".newVertexComponent .rightPaneTrashIconImg"); - elts[elts.length - 1].className += " deleteme"; - - document.querySelector(".newVertexComponent .rightPaneAddPropertyBtn").dispatchEvent(new Event("click")); - document - .querySelector(".newVertexComponent .rightPaneTrashIconImg.deleteme") - .parentElement.dispatchEvent(new Event("click")); - expect(document.getElementsByClassName("valueCol").length).toBe(2); - expect(document.getElementsByClassName("rightPaneTrashIcon").length).toBe(2); - expect(document.querySelectorAll(".newVertexComponent .rightPaneTrashIconImg.deleteme").length).toBe(0); - }); - }); -}); diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.html b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.html deleted file mode 100644 index 1c17d19c0..000000000 --- a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.html +++ /dev/null @@ -1,74 +0,0 @@ -
-
-
- - -
-
- - -
-
- -
-
- -
-
- -
-
-
- Remove property -
-
-
- - -
- - - Add property Add - Property - -
-
-
diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.less b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.less new file mode 100644 index 000000000..7f214d22d --- /dev/null +++ b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.less @@ -0,0 +1,97 @@ +@import "../../../../less/Common/Constants"; + +.newVertexComponent { + padding: @LargeSpace 20px 20px 0px; + width: 400px; + + .newVertexForm { + width: 100%; + .flex-display(); + .flex-direction(); + + .newVertexFormRow { + .flex-display(); + .flex-direction(@direction: row); + padding: 4px 5px; + + label { + padding: 0px; + } + + .valueCol { + flex-grow: 1; + padding-right: 5px; + } + + .rightPaneAddPropertyBtnPadding { + padding-top: 14px; + } + + .edgeLabel { + padding-right: 41px; + } + } + } + + .actionCol { + min-width: 30px; + padding: 0px 4px; + } + + .labelCol { + width: 72px; + min-width: 72px; + + input { + max-width: 65px; + padding-left: 4px; + } + } + + .edgeInput { + width: 100%; + padding-left: 4px; + } + + .typeSelect { + height: 23px; + width: 70px; + } + + .rightPaneTrashIcon { + padding: 4px 1px 0px 4px; + height: 100%; + } + + .rightPaneTrashIconImg { + vertical-align: top; + } + + .rightPaneAddPropertyBtn { + padding: 7px 7px 8px 8px; + margin-left: -8px; + } + + .rightPaneBtns { + cursor: pointer; + + &:hover { + background-color: @BaseLow; + } + + &:active { + background-color: @AccentMediumLow; + } + } + + .rightPaneAddPropertyImg { + margin-right: 5px; + margin-bottom: 4px; + } + + .contentScroll { + overflow-y: auto; + overflow-x: hidden; + white-space: nowrap; + } +} diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.test.tsx b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.test.tsx new file mode 100644 index 000000000..d6437bc85 --- /dev/null +++ b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.test.tsx @@ -0,0 +1,118 @@ +import { fireEvent, render, screen } from "@testing-library/react"; +import React from "react"; +import * as ViewModels from "../../../Contracts/ViewModels"; +import { NewVertexComponent } from "./NewVertexComponent"; + +describe("New Vertex Component", () => { + beforeEach(() => { + const fakeNewVertexData: ViewModels.NewVertexData = { + label: "", + properties: [ + { + key: "test1", + values: [ + { + value: "", + type: "string", + }, + ], + }, + ], + }; + const props = { + newVertexDataProp: fakeNewVertexData, + partitionKeyPropertyProp: "test1", + onChangeProp: (): void => undefined, + }; + + render(); + }); + + it("should render default prpoerty", () => { + const fakeNewVertexData: ViewModels.NewVertexData = { + label: "", + properties: [], + }; + const props = { + newVertexDataProp: fakeNewVertexData, + partitionKeyPropertyProp: "", + onChangeProp: (): void => undefined, + }; + + const { asFragment } = render(); + expect(asFragment).toMatchSnapshot(); + }); + + it("should render Add property button", () => { + const span = screen.getByText("Add Property"); + expect(span).toBeDefined(); + }); + + it("should call onAddNewProperty method on span click", () => { + const onAddNewProperty = jest.fn(); + const span = screen.getByText("Add Property"); + span.onclick = onAddNewProperty(); + fireEvent.click(span); + expect(onAddNewProperty).toHaveBeenCalled(); + }); + + it("should call onAddNewPropertyKeyPress method on span keyPress", () => { + const onAddNewPropertyKeyPress = jest.fn(); + const span = screen.getByText("Add Property"); + span.onkeypress = onAddNewPropertyKeyPress(); + fireEvent.keyPress(span, { key: "Enter", code: 13, charCode: 13 }); + expect(onAddNewPropertyKeyPress).toHaveBeenCalled(); + }); + + it("should call onLabelChange method on input change", () => { + const onLabelChange = jest.fn(); + const input = screen.getByLabelText("Label"); + input.onchange = onLabelChange(); + fireEvent.change(input, { target: { value: "Label" } }); + expect(onLabelChange).toHaveBeenCalled(); + }); + + it("should call onKeyChange method on key input change", () => { + const onKeyChange = jest.fn(); + const input = screen.queryByPlaceholderText("Key"); + input.onchange = onKeyChange(); + fireEvent.change(input, { target: { value: "pk1" } }); + expect(onKeyChange).toHaveBeenCalled(); + }); + + it("should call onValueChange method on value input change", () => { + const onValueChange = jest.fn(); + const input = screen.queryByPlaceholderText("Value"); + input.onchange = onValueChange(); + fireEvent.change(input, { target: { value: "abc" } }); + expect(onValueChange).toHaveBeenCalled(); + }); + + it("should call removeNewVertexProperty method on remove button click", () => { + const removeNewVertexProperty = jest.fn(); + const div = screen.getAllByRole("button"); + div[0].onclick = removeNewVertexProperty(); + fireEvent.click(div[0]); + expect(removeNewVertexProperty).toHaveBeenCalled(); + }); + + it("should call removeNewVertexProperty method on remove button keyPress", () => { + const removeNewVertexPropertyKeyPress = jest.fn(); + const div = screen.getAllByRole("button"); + div[0].onkeypress = removeNewVertexPropertyKeyPress(); + fireEvent.keyPress(div[0], { key: "Enter", code: 13, charCode: 13 }); + expect(removeNewVertexPropertyKeyPress).toHaveBeenCalled(); + }); + + it("should call onTypeChange method on type dropdown change", () => { + const DOWN_ARROW = { keyCode: 40 }; + const onTypeChange = jest.fn(); + const dropdown = screen.getByRole("listbox"); + dropdown.onclick = onTypeChange(); + dropdown.onkeydown = onTypeChange(); + + fireEvent.keyDown(screen.getByRole("listbox"), DOWN_ARROW); + fireEvent.click(screen.getByText(/number/)); + expect(onTypeChange).toHaveBeenCalled(); + }); +}); diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts deleted file mode 100644 index 50a3cead5..000000000 --- a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as ko from "knockout"; -import { EditorNodePropertiesComponent } from "../GraphExplorerComponent/EditorNodePropertiesComponent"; -import { NewVertexData, InputProperty } from "../../../Contracts/ViewModels"; -import { WaitsForTemplateViewModel } from "../../WaitsForTemplateViewModel"; -import * as Constants from "../../../Common/Constants"; -import template from "./NewVertexComponent.html"; - -/** - * Parameters for this component - */ -export interface NewVertexParams { - // Data to be edited by the component - newVertexData: ko.Observable; - partitionKeyProperty: ko.Observable; - firstFieldHasFocus?: ko.Observable; - - /** - * Callback triggered when the template is bound to the component (for testing purposes) - */ - onTemplateReady?: () => void; -} - -export class NewVertexViewModel extends WaitsForTemplateViewModel { - private static readonly DEFAULT_PROPERTY_TYPE = "string"; - - private newVertexData: ko.Observable; - private firstFieldHasFocus: ko.Observable; - private propertyTypes: string[]; - - public constructor(params: NewVertexParams) { - super(); - super.onTemplateReady((isTemplateReady: boolean) => { - if (isTemplateReady && params.onTemplateReady) { - params.onTemplateReady(); - } - }); - - this.newVertexData = - params.newVertexData || - ko.observable({ - label: "", - properties: [], - }); - this.firstFieldHasFocus = params.firstFieldHasFocus || ko.observable(false); - this.propertyTypes = EditorNodePropertiesComponent.VERTEX_PROPERTY_TYPES; - if (params.partitionKeyProperty) { - params.partitionKeyProperty.subscribe((newKeyProp: string) => { - if (!newKeyProp) { - return; - } - this.addNewVertexProperty(newKeyProp); - }); - } - } - - public onAddNewProperty() { - this.addNewVertexProperty(); - document.getElementById("propertyKeyNewVertexPane").focus(); - } - - public onAddNewPropertyKeyPress = (source: any, event: KeyboardEvent): boolean => { - if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) { - this.onAddNewProperty(); - event.stopPropagation(); - return false; - } - return true; - }; - - public addNewVertexProperty(key?: string) { - let ap = this.newVertexData().properties; - ap.push({ key: key || "", values: [{ value: "", type: NewVertexViewModel.DEFAULT_PROPERTY_TYPE }] }); - this.newVertexData.valueHasMutated(); - } - - public removeNewVertexProperty(index: number) { - let ap = this.newVertexData().properties; - ap.splice(index, 1); - this.newVertexData.valueHasMutated(); - document.getElementById("addProperyNewVertexBtn").focus(); - } - - public removeNewVertexPropertyKeyPress = (index: number, source: any, event: KeyboardEvent): boolean => { - if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) { - this.removeNewVertexProperty(index); - event.stopPropagation(); - return false; - } - return true; - }; -} - -/** - * Helper class for ko component registration - */ -export const NewVertexComponent = { - viewModel: NewVertexViewModel, - template, -}; diff --git a/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.tsx b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.tsx new file mode 100644 index 000000000..662dcba53 --- /dev/null +++ b/src/Explorer/Graph/NewVertexComponent/NewVertexComponent.tsx @@ -0,0 +1,213 @@ +import { Dropdown, IDropdownOption, Stack, TextField } from "office-ui-fabric-react"; +import React, { FunctionComponent, useRef, useState } from "react"; +import AddIcon from "../../../../images/Add-property.svg"; +import DeleteIcon from "../../../../images/delete.svg"; +import { NormalizedEventKey } from "../../../Common/Constants"; +import { GremlinPropertyValueType, InputPropertyValueTypeString, NewVertexData } from "../../../Contracts/ViewModels"; +import { EditorNodePropertiesComponent } from "../GraphExplorerComponent/EditorNodePropertiesComponent"; +import "./NewVertexComponent.less"; +export interface INewVertexComponentProps { + newVertexDataProp: NewVertexData; + partitionKeyPropertyProp: string; + onChangeProp: (labelData: NewVertexData) => void; +} + +export const NewVertexComponent: FunctionComponent = ({ + newVertexDataProp, + partitionKeyPropertyProp, + onChangeProp, +}: INewVertexComponentProps): JSX.Element => { + const DEFAULT_PROPERTY_TYPE = "string"; + const [newVertexData, setNewVertexData] = useState( + newVertexDataProp || { + label: "", + properties: [ + { + key: partitionKeyPropertyProp, + values: [{ value: "", type: DEFAULT_PROPERTY_TYPE }], + }, + ], + } + ); + + const propertyTypes: string[] = EditorNodePropertiesComponent.VERTEX_PROPERTY_TYPES; + const input = useRef(undefined); + + const onAddNewProperty = () => { + addNewVertexProperty(); + setTimeout(() => { + input.current.focus(); + }, 100); + }; + + const onAddNewPropertyKeyPress = (event: React.KeyboardEvent) => { + if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) { + onAddNewProperty(); + event.stopPropagation(); + } + }; + + const addNewVertexProperty = () => { + let key: string; + const ap = newVertexData.properties; + if (ap.length === 0) { + key = partitionKeyPropertyProp; + } + ap.push({ + key: key || "", + values: [{ value: "", type: DEFAULT_PROPERTY_TYPE }], + }); + setNewVertexData((prevData) => ({ + ...prevData, + properties: ap, + })); + onChangeProp(newVertexData); + }; + + const removeNewVertexProperty = (event?: React.MouseEvent, index?: number) => { + const ap = newVertexData.properties; + ap.splice(index, 1); + setNewVertexData((prevData) => ({ + ...prevData, + properties: ap, + })); + onChangeProp(newVertexData); + document.getElementById("addProperyNewVertexBtn").focus(); + }; + + const removeNewVertexPropertyKeyPress = (event: React.KeyboardEvent, index: number) => { + if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) { + removeNewVertexProperty(undefined, index); + event.stopPropagation(); + } + }; + + const onLabelChange = (event: React.ChangeEvent) => { + setNewVertexData((prevData) => ({ + ...prevData, + label: event.target.value, + })); + onChangeProp(newVertexData); + }; + + const onKeyChange = (event: React.ChangeEvent, index: number) => { + const newState = { ...newVertexData }; + newState.properties[index].key = event.target.value; + setNewVertexData(newState); + onChangeProp(newVertexData); + }; + + const onValueChange = (event: React.ChangeEvent, index: number) => { + const newState = { ...newVertexData }; + newState.properties[index].values[0].value = event.target.value as GremlinPropertyValueType; + setNewVertexData(newState); + onChangeProp(newVertexData); + }; + + const onTypeChange = (option: string, index: number) => { + const newState = { ...newVertexData }; + if (newState.properties[index]) { + newState.properties[index].values[0].type = option as InputPropertyValueTypeString; + setNewVertexData(newState); + onChangeProp(newVertexData); + } + }; + + return ( + +
+
+
+ ) => { + onLabelChange(event); + }} + /> +
+
+ {newVertexData.properties.map((data, index) => { + return ( +
+
+ ) => onKeyChange(event, index)} + /> +
+
+ ) => onValueChange(event, index)} + /> +
+
+ ({ + key: type, + text: type, + }))} + onChange={(_, options: IDropdownOption) => onTypeChange(options.key.toString(), index)} + /> +
+
+
) => removeNewVertexProperty(event, index)} + onKeyPress={(event: React.KeyboardEvent) => + removeNewVertexPropertyKeyPress(event, index) + } + > + Remove property +
+
+
+ ); + })} + +
+ + ) => onAddNewPropertyKeyPress(event)} + > + Add property Add Property + + +
+
+
+
+ ); +}; diff --git a/src/Explorer/Graph/NewVertexComponent/__snapshots__/NewVertexComponent.test.tsx.snap b/src/Explorer/Graph/NewVertexComponent/__snapshots__/NewVertexComponent.test.tsx.snap new file mode 100644 index 000000000..629578b2b --- /dev/null +++ b/src/Explorer/Graph/NewVertexComponent/__snapshots__/NewVertexComponent.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`New Vertex Component should render default prpoerty 1`] = `[Function]`; diff --git a/src/Explorer/Graph/NewVertexComponent/newVertexComponent.less b/src/Explorer/Graph/NewVertexComponent/newVertexComponent.less deleted file mode 100644 index 00547ced6..000000000 --- a/src/Explorer/Graph/NewVertexComponent/newVertexComponent.less +++ /dev/null @@ -1,97 +0,0 @@ -@import "../../../../less/Common/Constants"; - -.newVertexComponent { - padding: @LargeSpace 20px 20px 0px; - width: 400px; - - .newVertexForm { - width: 100%; - .flex-display(); - .flex-direction(); - - .newVertexFormRow { - .flex-display(); - .flex-direction(@direction: row); - padding: 4px 5px; - - label { - padding: 0px; - } - - .valueCol { - flex-grow: 1; - padding-right: 5px; - } - - .rightPaneAddPropertyBtnPadding { - padding-top: 14px; - } - - .edgeLabel { - padding-right: 41px; - } - } - } - - .actionCol { - min-width: 30px; - padding: 0px 4px; - } - - .labelCol { - width: 72px; - min-width: 72px; - - input { - max-width: 65px; - padding-left: 4px; - } - } - - .edgeInput { - width: 100%; - padding-left: 4px; - } - - .typeSelect { - height: 23px; - width: 70px; - } - - .rightPaneTrashIcon { - padding: 4px 1px 0px 4px; - height: 100%; - } - - .rightPaneTrashIconImg { - vertical-align: top; - } - - .rightPaneAddPropertyBtn { - padding: 7px 7px 8px 8px; - margin-left: -8px; - } - - .rightPaneBtns { - cursor: pointer; - - &:hover { - background-color: @BaseLow ; - } - - &:active { - background-color: @AccentMediumLow; - } - } - - .rightPaneAddPropertyImg { - margin-right: 5px; - margin-bottom: 4px; - } - - .contentScroll { - overflow-y: auto; - overflow-x: hidden; - white-space: nowrap; - } -} diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx index c80e0bf70..917470dd4 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx @@ -23,16 +23,13 @@ export class CommandBarComponentAdapter implements ReactAdapter { constructor(container: Explorer) { this.container = container; this.tabsButtons = []; - this.isNotebookTabActive = ko.computed(() => - container.tabsManager.isTabActive(ViewModels.CollectionTabKind.NotebookV2) + this.isNotebookTabActive = ko.computed( + () => container.tabsManager.activeTab()?.tabKind === ViewModels.CollectionTabKind.NotebookV2 ); // These are the parameters watched by the react binding that will trigger a renderComponent() if one of the ko mutates const toWatch = [ - container.isPreferredApiTable, container.isPreferredApiMongoDB, - container.isPreferredApiCassandra, - container.isPreferredApiGraph, container.deleteCollectionText, container.deleteDatabaseText, container.addCollectionText, diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts index a4874f0e3..33fa59e0e 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts @@ -1,5 +1,6 @@ import * as ko from "knockout"; import { AuthType } from "../../../AuthType"; +import { DatabaseAccount } from "../../../Contracts/DataModels"; import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService"; import { updateUserContext } from "../../../UserContext"; import Explorer from "../../Explorer"; @@ -15,9 +16,14 @@ describe("CommandBarComponentButtonFactory tests", () => { beforeAll(() => { mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); - mockExplorer.isPreferredApiTable = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableTable" }], + }, + } as DatabaseAccount, + }); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); - mockExplorer.isPreferredApiCassandra = ko.computed(() => false); mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSynapseLinkUpdating = ko.observable(false); @@ -54,9 +60,14 @@ describe("CommandBarComponentButtonFactory tests", () => { beforeAll(() => { mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); - mockExplorer.isPreferredApiTable = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableTable" }], + }, + } as DatabaseAccount, + }); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); - mockExplorer.isPreferredApiCassandra = ko.computed(() => false); mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSynapseLinkUpdating = ko.observable(false); @@ -118,8 +129,13 @@ describe("CommandBarComponentButtonFactory tests", () => { beforeAll(() => { mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); - mockExplorer.isPreferredApiTable = ko.computed(() => true); - mockExplorer.isPreferredApiCassandra = ko.computed(() => false); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableTable" }], + }, + } as DatabaseAccount, + }); mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSynapseLinkUpdating = ko.observable(false); @@ -197,8 +213,15 @@ describe("CommandBarComponentButtonFactory tests", () => { beforeAll(() => { mockExplorer = {} as Explorer; + mockExplorer.addDatabaseText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText"); - mockExplorer.isPreferredApiTable = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableTable" }], + }, + } as DatabaseAccount, + }); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); @@ -208,15 +231,27 @@ describe("CommandBarComponentButtonFactory tests", () => { }); beforeEach(() => { - mockExplorer.isPreferredApiCassandra = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableCassandra" }], + }, + } as DatabaseAccount, + }); mockExplorer.isNotebookEnabled = ko.observable(false); mockExplorer.isNotebooksEnabledForAccount = ko.observable(false); mockExplorer.isRunningOnNationalCloud = ko.observable(false); }); it("Cassandra Api not available - button should be hidden", () => { - mockExplorer.isPreferredApiCassandra = ko.computed(() => false); - + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableMongo" }], + }, + } as DatabaseAccount, + }); + console.log(mockExplorer); const buttons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(mockExplorer); const openCassandraShellBtn = buttons.find((button) => button.commandButtonLabel === openCassandraShellBtnLabel); expect(openCassandraShellBtn).toBeUndefined(); @@ -279,9 +314,14 @@ describe("CommandBarComponentButtonFactory tests", () => { beforeAll(() => { mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); - mockExplorer.isPreferredApiTable = ko.computed(() => true); + updateUserContext({ + databaseAccount: { + properties: { + capabilities: [{ name: "EnableTable" }], + }, + } as DatabaseAccount, + }); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); - mockExplorer.isPreferredApiCassandra = ko.computed(() => false); mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); @@ -346,6 +386,11 @@ describe("CommandBarComponentButtonFactory tests", () => { }); it("should only show New SQL Query and Open Query buttons", () => { + updateUserContext({ + databaseAccount: { + kind: "DocumentDB", + } as DatabaseAccount, + }); const buttons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(mockExplorer); expect(buttons.length).toBe(2); expect(buttons[0].commandButtonLabel).toBe("New SQL Query"); diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx index 7ba6f8645..3f3533f66 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx @@ -47,7 +47,7 @@ export function createStaticCommandBarButtons(container: Explorer): CommandButto buttons.push(addSynapseLink); } - if (!container.isPreferredApiTable()) { + if (userContext.apiType !== "Tables") { newCollectionBtn.children = [createNewCollectionGroup(container)]; const newDatabaseBtn = createNewDatabase(container); newCollectionBtn.children.push(newDatabaseBtn); @@ -74,7 +74,7 @@ export function createStaticCommandBarButtons(container: Explorer): CommandButto buttons.push(createOpenMongoTerminalButton(container)); } - if (container.isPreferredApiCassandra()) { + if (userContext.apiType === "Cassandra") { buttons.push(createOpenCassandraTerminalButton(container)); } } @@ -90,15 +90,15 @@ export function createStaticCommandBarButtons(container: Explorer): CommandButto buttons.push(createDivider()); } - const isSqlQuerySupported = userContext.apiType === "SQL" || container.isPreferredApiGraph(); + const isSqlQuerySupported = userContext.apiType === "SQL" || userContext.apiType === "Gremlin"; if (isSqlQuerySupported) { const newSqlQueryBtn = createNewSQLQueryButton(container); buttons.push(newSqlQueryBtn); } const isSupportedOpenQueryApi = - userContext.apiType === "SQL" || container.isPreferredApiMongoDB() || container.isPreferredApiGraph(); - const isSupportedOpenQueryFromDiskApi = userContext.apiType === "SQL" || container.isPreferredApiGraph(); + userContext.apiType === "SQL" || container.isPreferredApiMongoDB() || userContext.apiType === "Gremlin"; + const isSupportedOpenQueryFromDiskApi = userContext.apiType === "SQL" || userContext.apiType === "Gremlin"; if (isSupportedOpenQueryApi && container.selectedNode() && container.findSelectedCollection()) { const openQueryBtn = createOpenQueryButton(container); openQueryBtn.children = [createOpenQueryButton(container), createOpenQueryFromDiskButton(container)]; @@ -107,7 +107,7 @@ export function createStaticCommandBarButtons(container: Explorer): CommandButto buttons.push(createOpenQueryFromDiskButton(container)); } - if (areScriptsSupported(container)) { + if (areScriptsSupported()) { const label = "New Stored Procedure"; const newStoredProcedureBtn: CommandButtonComponentProps = { iconSrc: AddStoredProcedureIcon, @@ -216,8 +216,8 @@ export function createDivider(): CommandButtonComponentProps { }; } -function areScriptsSupported(container: Explorer): boolean { - return userContext.apiType === "SQL" || container.isPreferredApiGraph(); +function areScriptsSupported(): boolean { + return userContext.apiType === "SQL" || userContext.apiType === "Gremlin"; } function createNewCollectionGroup(container: Explorer): CommandButtonComponentProps { @@ -289,7 +289,7 @@ function createNewDatabase(container: Explorer): CommandButtonComponentProps { } function createNewSQLQueryButton(container: Explorer): CommandButtonComponentProps { - if (userContext.apiType === "SQL" || container.isPreferredApiGraph()) { + if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") { const label = "New SQL Query"; return { iconSrc: AddSqlQueryIcon, @@ -303,7 +303,7 @@ function createNewSQLQueryButton(container: Explorer): CommandButtonComponentPro hasPopup: true, disabled: container.isDatabaseNodeOrNoneSelected(), }; - } else if (container.isPreferredApiMongoDB()) { + } else if (userContext.apiType === "Mongo") { const label = "New Query"; return { iconSrc: AddSqlQueryIcon, @@ -325,8 +325,7 @@ function createNewSQLQueryButton(container: Explorer): CommandButtonComponentPro export function createScriptCommandButtons(container: Explorer): CommandButtonComponentProps[] { const buttons: CommandButtonComponentProps[] = []; - const shouldEnableScriptsCommands: boolean = - !container.isDatabaseNodeOrNoneSelected() && areScriptsSupported(container); + const shouldEnableScriptsCommands: boolean = !container.isDatabaseNodeOrNoneSelected() && areScriptsSupported(); if (shouldEnableScriptsCommands) { const label = "New Stored Procedure"; @@ -446,7 +445,7 @@ function createEnableNotebooksButton(container: Explorer): CommandButtonComponen return { iconSrc: EnableNotebooksIcon, iconAlt: label, - onCommandClick: () => container.setupNotebooksPane.openWithTitleAndDescription(label, description), + onCommandClick: () => container.openSetupNotebooksPanel(label, description), commandButtonLabel: label, hasPopup: false, disabled: !container.isNotebooksEnabledForAccount(), @@ -483,7 +482,7 @@ function createOpenMongoTerminalButton(container: Explorer): CommandButtonCompon if (container.isNotebookEnabled()) { container.openNotebookTerminal(ViewModels.TerminalKind.Mongo); } else { - container.setupNotebooksPane.openWithTitleAndDescription(title, description); + container.openSetupNotebooksPanel(title, description); } }, commandButtonLabel: label, @@ -509,7 +508,7 @@ function createOpenCassandraTerminalButton(container: Explorer): CommandButtonCo if (container.isNotebookEnabled()) { container.openNotebookTerminal(ViewModels.TerminalKind.Cassandra); } else { - container.setupNotebooksPane.openWithTitleAndDescription(title, description); + container.openSetupNotebooksPanel(title, description); } }, commandButtonLabel: label, diff --git a/src/Explorer/Notebook/NotebookClientV2.ts b/src/Explorer/Notebook/NotebookClientV2.ts index 940be1e3a..e7c1fa289 100644 --- a/src/Explorer/Notebook/NotebookClientV2.ts +++ b/src/Explorer/Notebook/NotebookClientV2.ts @@ -34,8 +34,6 @@ import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import { userContext } from "../../UserContext"; import configureStore from "./NotebookComponent/store"; import { CdbAppState, makeCdbRecord } from "./NotebookComponent/types"; -import SandboxJavaScript from "./NotebookRenderer/outputs/SandboxJavaScript"; -import SanitizedHTML from "./NotebookRenderer/outputs/SanitizedHTML"; export type KernelSpecsDisplay = { name: string; displayName: string }; @@ -125,62 +123,62 @@ export class NotebookClientV2 { contents: makeContentsRecord({ byRef: Immutable.Map(), }), - transforms: makeTransformsRecord({ - displayOrder: Immutable.List([ - "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.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", - ]), - byId: Immutable.Map({ - "text/vnd.plotly.v1+html": NullTransform, - "application/vnd.plotly.v1+json": NullTransform, - "application/geo+json": NullTransform, - "application/x-nteract-model-debug+json": NullTransform, - "application/vnd.dataresource+json": NullTransform, - "application/vnd.jupyter.widget-view+json": NullTransform, - "application/vnd.vegalite.v1+json": NullTransform, - "application/vnd.vegalite.v2+json": NullTransform, - "application/vnd.vegalite.v3+json": NullTransform, - "application/vnd.vega.v2+json": NullTransform, - "application/vnd.vega.v3+json": NullTransform, - "application/vnd.vega.v4+json": NullTransform, - "application/vnd.vega.v5+json": NullTransform, - "application/vdom.v1+json": TransformVDOM, - "application/json": Media.Json, - "application/javascript": userContext.features.sandboxNotebookOutputs - ? SandboxJavaScript - : Media.JavaScript, - "text/html": userContext.features.sandboxNotebookOutputs ? SanitizedHTML : Media.HTML, - "text/markdown": Media.Markdown, - "text/latex": Media.LaTeX, - "image/svg+xml": Media.SVG, - "image/gif": Media.Image, - "image/png": Media.Image, - "image/jpeg": Media.Image, - "text/plain": Media.Plain, - }), - }), + transforms: userContext.features.sandboxNotebookOutputs + ? undefined + : makeTransformsRecord({ + displayOrder: Immutable.List([ + "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.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", + ]), + byId: Immutable.Map({ + "text/vnd.plotly.v1+html": NullTransform, + "application/vnd.plotly.v1+json": NullTransform, + "application/geo+json": NullTransform, + "application/x-nteract-model-debug+json": NullTransform, + "application/vnd.dataresource+json": NullTransform, + "application/vnd.jupyter.widget-view+json": NullTransform, + "application/vnd.vegalite.v1+json": NullTransform, + "application/vnd.vegalite.v2+json": NullTransform, + "application/vnd.vegalite.v3+json": NullTransform, + "application/vnd.vega.v2+json": NullTransform, + "application/vnd.vega.v3+json": NullTransform, + "application/vnd.vega.v4+json": NullTransform, + "application/vnd.vega.v5+json": NullTransform, + "application/vdom.v1+json": TransformVDOM, + "application/json": Media.Json, + "application/javascript": Media.JavaScript, + "text/html": Media.HTML, + "text/markdown": Media.Markdown, + "text/latex": Media.LaTeX, + "image/svg+xml": Media.SVG, + "image/gif": Media.Image, + "image/png": Media.Image, + "image/jpeg": Media.Image, + "text/plain": Media.Plain, + }), + }), }), }), cdb: makeCdbRecord({ @@ -202,10 +200,11 @@ export class NotebookClientV2 { case actions.FETCH_KERNELSPECS_FULFILLED: { const payload = ((action as unknown) as actions.FetchKernelspecsFulfilled).payload; const defaultKernelName = payload.defaultKernelName; - this.kernelSpecsForDisplay = Object.keys(payload.kernelspecs) - .map((name) => ({ - name, - displayName: payload.kernelspecs[name].displayName, + this.kernelSpecsForDisplay = Object.values(payload.kernelspecs) + .filter((spec) => !spec.metadata?.hasOwnProperty("hidden")) + .map((spec) => ({ + name: spec.name, + displayName: spec.displayName, })) .sort((a: KernelSpecsDisplay, b: KernelSpecsDisplay) => { // Put default at the top, otherwise lexicographically compare diff --git a/src/Explorer/Notebook/NotebookComponent/epics.ts b/src/Explorer/Notebook/NotebookComponent/epics.ts index 544f80bf4..8c8610c0a 100644 --- a/src/Explorer/Notebook/NotebookComponent/epics.ts +++ b/src/Explorer/Notebook/NotebookComponent/epics.ts @@ -1,52 +1,49 @@ -import { EMPTY, merge, of, timer, concat, Subject, Subscriber, Observable, Observer, from } from "rxjs"; -import { webSocket } from "rxjs/webSocket"; -import { StateObservable } from "redux-observable"; -import { ofType } from "redux-observable"; import { - mergeMap, - tap, - retryWhen, - delayWhen, - map, - switchMap, - take, - filter, - catchError, - first, - concatMap, - timeout, -} from "rxjs/operators"; -import { - AppState, - ServerConfig as JupyterServerConfig, - JupyterHostRecordProps, - RemoteKernelProps, - castToSessionId, - createKernelRef, - KernelRef, - ContentRef, - KernelInfo, actions, + AppState, + castToSessionId, + ContentRef, + createKernelRef, + JupyterHostRecordProps, + KernelInfo, + KernelRef, + RemoteKernelProps, selectors, + ServerConfig as JupyterServerConfig, } from "@nteract/core"; -import { message, JupyterMessage, Channels, createMessage, childOf, ofMessageType } from "@nteract/messaging"; -import { sessions, kernels } from "rx-jupyter"; +import { Channels, childOf, createMessage, JupyterMessage, message, ofMessageType } from "@nteract/messaging"; import { RecordOf } from "immutable"; import { AnyAction } from "redux"; - +import { ofType, StateObservable } from "redux-observable"; +import { kernels, sessions } from "rx-jupyter"; +import { concat, EMPTY, from, merge, Observable, Observer, of, Subject, Subscriber, timer } from "rxjs"; +import { + catchError, + concatMap, + delayWhen, + filter, + first, + map, + mergeMap, + retryWhen, + switchMap, + take, + tap, + timeout, +} from "rxjs/operators"; +import { webSocket } from "rxjs/webSocket"; import * as Constants from "../../../Common/Constants"; -import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils"; -import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent"; -import * as CdbActions from "./actions"; -import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; +import { Areas } from "../../../Common/Constants"; import { Action as TelemetryAction, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; -import { CdbAppState } from "./types"; +import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import { decryptJWTToken } from "../../../Utils/AuthorizationUtils"; -import * as TextFile from "./contents/file/text-file"; -import { NotebookUtil } from "../NotebookUtil"; +import { logConsoleError, logConsoleInfo } from "../../../Utils/NotificationConsoleUtils"; import * as FileSystemUtil from "../FileSystemUtil"; import * as cdbActions from "../NotebookComponent/actions"; -import { Areas } from "../../../Common/Constants"; +import { NotebookUtil } from "../NotebookUtil"; +import * as CdbActions from "./actions"; +import * as TextFile from "./contents/file/text-file"; +import { CdbAppState } from "./types"; interface NotebookServiceConfig extends JupyterServerConfig { userPuid?: string; @@ -311,7 +308,7 @@ export const launchWebSocketKernelEpic = ( if (currentKernelspecs) { kernelSpecToLaunch = currentKernelspecs.defaultKernelName; const msg = `No kernelspec name specified to launch, using default kernel: ${kernelSpecToLaunch}`; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, msg); + logConsoleInfo(msg); logFailureToTelemetry(state$.value, "Launching alternate kernel", msg); } else { return of( @@ -337,7 +334,7 @@ export const launchWebSocketKernelEpic = ( kernelSpecToLaunch = currentKernelspecs.defaultKernelName; msg += ` Using default kernel: ${kernelSpecToLaunch}`; } - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, msg); + logConsoleInfo(msg); logFailureToTelemetry(state$.value, "Launching alternate kernel", msg); } @@ -634,7 +631,7 @@ const notificationsToUserEpic = (action$: Observable, state$: StateObservab case actions.RESTART_KERNEL_SUCCESSFUL: { const title = "Kernel restart"; const msg = "Kernel successfully restarted"; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, msg); + logConsoleInfo(msg); logFailureToTelemetry(state$.value, title, msg); break; } @@ -645,7 +642,7 @@ const notificationsToUserEpic = (action$: Observable, state$: StateObservab case actions.SAVE_FAILED: { const title = "Save failure"; const msg = `Failed to save notebook: ${(action as actions.SaveFailed).payload.error}`; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); logFailureToTelemetry(state$.value, title, msg); break; } @@ -654,7 +651,7 @@ const notificationsToUserEpic = (action$: Observable, state$: StateObservab const filepath = selectors.filepath(state$.value, { contentRef: typedAction.payload.contentRef }); const title = "Fetching content failure"; const msg = `Failed to fetch notebook content: ${filepath}, error: ${typedAction.payload.error}`; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); logFailureToTelemetry(state$.value, title, msg); break; } @@ -679,7 +676,7 @@ const handleKernelConnectionLostEpic = ( const state = state$.value; const msg = "Notebook was disconnected from kernel"; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); logFailureToTelemetry(state, "Error", "Kernel connection error"); const host = selectors.currentHost(state); @@ -692,7 +689,7 @@ const handleKernelConnectionLostEpic = ( if (delayMs > Constants.Notebook.kernelRestartMaxDelayMs) { const msg = "Restarted kernel too many times. Please reload the page to enable Data Explorer to restart the kernel automatically."; - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); logFailureToTelemetry(state, "Kernel restart error", msg); const explorer = window.dataExplorer; @@ -810,7 +807,7 @@ const closeUnsupportedMimetypesEpic = ( ); const msg = `${filepath} cannot be rendered. Please download the file, in order to view it outside of Data Explorer.`; explorer.showOkModalDialog("File cannot be rendered", msg); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); } return EMPTY; }) @@ -838,7 +835,7 @@ const closeContentFailedToFetchEpic = ( ); const msg = `Failed to load file: ${filepath}.`; explorer.showOkModalDialog("Failure to load", msg); - NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, msg); + logConsoleError(msg); } return EMPTY; }) diff --git a/src/Explorer/Notebook/NotebookContainerClient.ts b/src/Explorer/Notebook/NotebookContainerClient.ts index 7d5a82318..33863c8cb 100644 --- a/src/Explorer/Notebook/NotebookContainerClient.ts +++ b/src/Explorer/Notebook/NotebookContainerClient.ts @@ -1,15 +1,14 @@ /** * Notebook container related stuff */ -import * as DataModels from "../../Contracts/DataModels"; import * as Constants from "../../Common/Constants"; -import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; -import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils"; -import * as Logger from "../../Common/Logger"; import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; +import * as Logger from "../../Common/Logger"; +import * as DataModels from "../../Contracts/DataModels"; +import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; export class NotebookContainerClient { - private reconnectingNotificationId: string; + private clearReconnectionAttemptMessage? = () => {}; private isResettingWorkspace: boolean; constructor( @@ -61,9 +60,9 @@ export class NotebookContainerClient { }, }); if (response.ok) { - if (this.reconnectingNotificationId) { - NotificationConsoleUtils.clearInProgressMessageWithId(this.reconnectingNotificationId); - this.reconnectingNotificationId = ""; + if (this.clearReconnectionAttemptMessage) { + this.clearReconnectionAttemptMessage(); + this.clearReconnectionAttemptMessage = undefined; } const memoryUsageInfo = await response.json(); if (memoryUsageInfo) { @@ -76,9 +75,8 @@ export class NotebookContainerClient { return undefined; } catch (error) { Logger.logError(getErrorMessage(error), "NotebookContainerClient/getMemoryUsage"); - if (!this.reconnectingNotificationId) { - this.reconnectingNotificationId = NotificationConsoleUtils.logConsoleMessage( - ConsoleDataType.InProgress, + if (!this.clearReconnectionAttemptMessage) { + this.clearReconnectionAttemptMessage = logConsoleProgress( "Connection lost with Notebook server. Attempting to reconnect..." ); } diff --git a/src/Explorer/Notebook/NotebookManager.ts b/src/Explorer/Notebook/NotebookManager.tsx similarity index 92% rename from src/Explorer/Notebook/NotebookManager.ts rename to src/Explorer/Notebook/NotebookManager.tsx index b59c3377b..42f41baf5 100644 --- a/src/Explorer/Notebook/NotebookManager.ts +++ b/src/Explorer/Notebook/NotebookManager.tsx @@ -2,30 +2,31 @@ * Contains all notebook related stuff meant to be dynamically loaded by explorer */ -import { JunoClient } from "../../Juno/JunoClient"; -import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService"; -import { GitHubClient } from "../../GitHub/GitHubClient"; -import * as Logger from "../../Common/Logger"; -import { HttpStatusCodes, Areas } from "../../Common/Constants"; -import { GitHubReposPane } from "../Panes/GitHubReposPane"; -import ko from "knockout"; -import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; -import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; -import { IContentProvider } from "@nteract/core"; -import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider"; -import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider"; -import { contents } from "rx-jupyter"; -import { NotebookContainerClient } from "./NotebookContainerClient"; -import { MemoryUsageInfo } from "../../Contracts/DataModels"; -import { NotebookContentClient } from "./NotebookContentClient"; -import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; -import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter"; -import { getFullName } from "../../Utils/UserUtils"; import { ImmutableNotebook } from "@nteract/commutable"; +import { IContentProvider } from "@nteract/core"; +import ko from "knockout"; +import React from "react"; +import { contents } from "rx-jupyter"; +import { Areas, HttpStatusCodes } from "../../Common/Constants"; +import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; +import * as Logger from "../../Common/Logger"; +import { MemoryUsageInfo } from "../../Contracts/DataModels"; +import { GitHubClient } from "../../GitHub/GitHubClient"; +import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider"; +import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService"; +import { JunoClient } from "../../Juno/JunoClient"; +import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; +import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import { getFullName } from "../../Utils/UserUtils"; import Explorer from "../Explorer"; import { ContextualPaneBase } from "../Panes/ContextualPaneBase"; -import { CopyNotebookPaneAdapter } from "../Panes/CopyNotebookPane"; -import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; +import { CopyNotebookPane } from "../Panes/CopyNotebookPane/CopyNotebookPane"; +import { GitHubReposPane } from "../Panes/GitHubReposPane"; +import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter"; +import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; +import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider"; +import { NotebookContainerClient } from "./NotebookContainerClient"; +import { NotebookContentClient } from "./NotebookContentClient"; export interface NotebookManagerOptions { container: Explorer; @@ -49,7 +50,6 @@ export default class NotebookManager { public gitHubReposPane: ContextualPaneBase; public publishNotebookPaneAdapter: PublishNotebookPaneAdapter; - public copyNotebookPaneAdapter: CopyNotebookPaneAdapter; public initialize(params: NotebookManagerOptions): void { this.params = params; @@ -89,12 +89,6 @@ export default class NotebookManager { this.publishNotebookPaneAdapter = new PublishNotebookPaneAdapter(this.params.container, this.junoClient); - this.copyNotebookPaneAdapter = new CopyNotebookPaneAdapter( - this.params.container, - this.junoClient, - this.gitHubOAuthService - ); - this.gitHubOAuthService.getTokenObservable().subscribe((token) => { this.gitHubClient.setToken(token?.access_token); @@ -129,7 +123,18 @@ export default class NotebookManager { } public openCopyNotebookPane(name: string, content: string): void { - this.copyNotebookPaneAdapter.open(name, content); + const { container } = this.params; + container.openSidePanel( + "Copy Notebook", + + ); } // Octokit's error handler uses any diff --git a/src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx b/src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx index 75133d7f3..ceef02cbb 100644 --- a/src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx +++ b/src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx @@ -1,10 +1,8 @@ import { actions, ContentRef } from "@nteract/core"; -import { KernelOutputError, StreamText } from "@nteract/outputs"; import { Cells, CodeCell, MarkdownCell, RawCell } from "@nteract/stateful-components"; import MonacoEditor from "@nteract/stateful-components/lib/inputs/connected-editors/monacoEditor"; import { PassedEditorProps } from "@nteract/stateful-components/lib/inputs/editor"; import Prompt, { PassedPromptProps } from "@nteract/stateful-components/lib/inputs/prompt"; -import TransformMedia from "@nteract/stateful-components/lib/outputs/transform-media"; import * as React from "react"; import { connect } from "react-redux"; import { Dispatch } from "redux"; @@ -14,7 +12,7 @@ import { AzureTheme } from "./AzureTheme"; import "./base.css"; import "./default.css"; import "./NotebookReadOnlyRenderer.less"; -import IFrameOutputs from "./outputs/IFrameOutputs"; +import SandboxOutputs from "./outputs/SandboxOutputs"; export interface NotebookRendererProps { contentRef: any; @@ -27,7 +25,9 @@ export interface NotebookRendererProps { */ class NotebookReadOnlyRenderer extends React.Component { componentDidMount() { - loadTransform(this.props as any); + if (!userContext.features.sandboxNotebookOutputs) { + loadTransform(this.props as any); + } } private renderPrompt(id: string, contentRef: string): JSX.Element { @@ -63,14 +63,7 @@ class NotebookReadOnlyRenderer extends React.Component { {{ prompt: (props: { id: string; contentRef: string }) => this.renderPrompt(props.id, props.contentRef), outputs: userContext.features.sandboxNotebookOutputs - ? (props: any) => ( - - - - - - - ) + ? () => : undefined, editor: { monaco: (props: PassedEditorProps) => diff --git a/src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx b/src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx index b78fdab97..876cbf337 100644 --- a/src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx +++ b/src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx @@ -1,11 +1,9 @@ import { CellId } from "@nteract/commutable"; import { CellType } from "@nteract/commutable/src"; import { actions, ContentRef } from "@nteract/core"; -import { KernelOutputError, StreamText } from "@nteract/outputs"; import { Cells, CodeCell, RawCell } from "@nteract/stateful-components"; import MonacoEditor from "@nteract/stateful-components/lib/inputs/connected-editors/monacoEditor"; import { PassedEditorProps } from "@nteract/stateful-components/lib/inputs/editor"; -import TransformMedia from "@nteract/stateful-components/lib/outputs/transform-media"; import * as React from "react"; import { DndProvider } from "react-dnd"; import HTML5Backend from "react-dnd-html5-backend"; @@ -23,7 +21,7 @@ import KeyboardShortcuts from "./decorators/kbd-shortcuts"; import "./default.css"; import MarkdownCell from "./markdown-cell"; import "./NotebookRenderer.less"; -import IFrameOutputs from "./outputs/IFrameOutputs"; +import SandboxOutputs from "./outputs/SandboxOutputs"; import Prompt from "./Prompt"; import { promptContent } from "./PromptContent"; import StatusBar from "./StatusBar"; @@ -71,7 +69,9 @@ class BaseNotebookRenderer extends React.Component { } componentDidMount() { - loadTransform(this.props as any); + if (!userContext.features.sandboxNotebookOutputs) { + loadTransform(this.props as any); + } this.props.updateNotebookParentDomElt(this.props.contentRef, this.notebookRendererRef.current); } @@ -109,14 +109,7 @@ class BaseNotebookRenderer extends React.Component { ), toolbar: () => , outputs: userContext.features.sandboxNotebookOutputs - ? (props: any) => ( - - - - - - - ) + ? () => : undefined, }} diff --git a/src/Explorer/Notebook/NotebookRenderer/outputs/IFrameOutputs.tsx b/src/Explorer/Notebook/NotebookRenderer/outputs/IFrameOutputs.tsx deleted file mode 100644 index 8ca9764f5..000000000 --- a/src/Explorer/Notebook/NotebookRenderer/outputs/IFrameOutputs.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { AppState, ContentRef, selectors } from "@nteract/core"; -import { Output } from "@nteract/outputs"; -import Immutable from "immutable"; -import React from "react"; -import { connect } from "react-redux"; -import { SandboxFrame } from "./SandboxFrame"; - -// Adapted from https://github.com/nteract/nteract/blob/main/packages/stateful-components/src/outputs/index.tsx -// to add support for sandboxing using - ); - } - - componentWillUnmount(): void { - this.resizeObserver?.disconnect(); - this.mutationObserver?.disconnect(); - } - - onFrameLoad(event: React.SyntheticEvent): void { - const doc = (event.target as HTMLIFrameElement).contentDocument; - copyStyles(document, doc); - - this.setState({ frameBody: doc.body }); - - this.mutationObserver = new MutationObserver(() => { - const bodyFirstElementChild = this.state.frameBody?.firstElementChild; - if (!this.resizeObserver && bodyFirstElementChild) { - this.resizeObserver = new ResizeObserver(() => - this.setState({ - frameHeight: this.state.frameBody?.firstElementChild.scrollHeight, - }) - ); - this.resizeObserver.observe(bodyFirstElementChild); - } - }); - this.mutationObserver.observe(doc.body, { childList: true }); - } -} diff --git a/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxJavaScript.tsx b/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxJavaScript.tsx deleted file mode 100644 index c6420a30e..000000000 --- a/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxJavaScript.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Media } from "@nteract/outputs"; -import React from "react"; - -interface Props { - /** - * The JavaScript code that we would like to execute. - */ - data: string; - /** - * The media type associated with our component. - */ - mediaType: "text/javascript"; -} - -export class SandboxJavaScript extends React.PureComponent { - static defaultProps = { - data: "", - mediaType: "application/javascript", - }; - - render(): JSX.Element { - return ${this.props.data}`} />; - } -} - -export default SandboxJavaScript; diff --git a/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxOutputs.tsx b/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxOutputs.tsx new file mode 100644 index 000000000..40f42fd35 --- /dev/null +++ b/src/Explorer/Notebook/NotebookRenderer/outputs/SandboxOutputs.tsx @@ -0,0 +1,132 @@ +import { JSONObject } from "@nteract/commutable"; +import { outputToJS } from "@nteract/commutable/lib/v4"; +import { actions, AppState, ContentRef, selectors } from "@nteract/core"; +import IframeResizer from "iframe-resizer-react"; +import Immutable from "immutable"; +import postRobot from "post-robot"; +import React from "react"; +import { connect } from "react-redux"; +import { Dispatch } from "redux"; +import { CellOutputViewerProps } from "../../../../CellOutputViewer/CellOutputViewer"; + +// Adapted from https://github.com/nteract/nteract/blob/main/packages/stateful-components/src/outputs/index.tsx +// to add support for sandboxing using